spring curity oauth2的demo在前几篇文章中已经讲过了,在那些模式中使用的都是remotetokenrvice调用授权服务器来校验token,返回校验通过的用户信息供上下文中获取
这种方式会加重授权服务器的负载,你想啊,当用户没授权时候获取token得找授权服务器,有token了访问资源服务器还要访问授权服务器,相当于说每次请求都要访问授权服务器,这样对授权服务器的负载会很大
常规的方式有两种来解决这个问题:
使用jwt作为token传递使用redis存储token,资源服务器本地访问redis校验token使用jwt与redis都可以在资源服务器中进行校验token,从而减少授权服务器的工作量
jwt默认使用hmacsha256对称加密算法,以下记录下默认算法实现与非对称rsa算法的集成,使用不同算法加解密测试方法是一致的,所以放在文章最后
授权服务器整体代码结构
pom.xml中引入依赖
<dependency> <groupid>org.springframework.boot</groupid> <artif重大安全事故actid>spring-boot-starter-curity</artifactid> <version>2.2.1.relea</version> </dependency> <!-- spring curity oauth2 --> <dependency> <groupid>org.springframework.curity.oauth</groupid> <artifactid>spring-curity-oauth2</artifactid> <version>2.4.0.relea</version> </dependency> <dependency> <groupid>org.springframework.curity</groupid> <artifactid>spring-curity-jwt</artifactid> <version>1.1.0.relea</version> </dependency>
curityconfig配置,主要需要显式声明authenticationmanager和urdetailsrvice这两个bean
@configuration@enablewebcuritypublic class curityconfig extends webcurityconfigureradapter { @bean public authenticationmanager authenticationmanager() throws exception { return super.authenticationmanager(); } @bean public urdetailsrvice urdetailsrvice(){ //主要是配置这个bean,用于授权服务器配置中注入 return super.urdetailsrvice(); } @bean public passwordencoder passwordencoder(){ return new bcryptpasswordencoder(); } @override protected void configure(authenticationmanagerbuilder auth) throws exception { // @formatter: off auth.inmemoryauthentication() .withur("hellxz") .password(passwordencoder().encode("xyz")) .authorities(collections.emptylist()); // @formatter: on } @override protected void configure(httpcurity http) throws exception { http.authorizerequests() .anyrequest().authenticated() //所有请求都需要通过认证 .and() .httpbasic() //basic提交 .and() .csrf().disable(); //关跨域保护 }}
授权服务器配置authorizationconfig
@configuration@enableauthorizationrver //开启授权服务public class authorizationconfig extends authorizationrverconfigureradapter { @autowired private authenticationm成都旅游攻略自由行攻略anager authenticationmanager; @autowired public urdetailsrvice urdetailsrvice; @autowired private passwordencoder passwordencoder; @override public void configure(authorizationrvercurityconfigurer curity) throws exception { //允许表单提交 curity.allowformauthenticationforclients() .checktokenaccess("permitall()") .tokenkeyaccess("permitall()"); } @override public void configure(clientdetailsrviceconfigurer clients) throws exception { // @formatter: off clients.inmemory() .withclient("client-a") //client端唯一标识 .cret(passwordencoder.encode("client-a-cret")) //client-a的密码,这里的密码应该是加密后的 .authorizedgranttypes("authorization_code", "password", "refresh_token") //授权模式标识,这里主要测试用password模式,另外refresh_token不是一种模式,但是可以使用它来刷新access_token(在它的有效期内) .scopes("read_ur_info") //作用域 .resourceids("resource1") //资源id,如不需限制资源id,注释此处即可 .redirecturis("http://localhost:9001/callback"); //回调地址 // @formatter: on } @override public void configure(authorizationrverendpointsconfigurer endpoints) throws exception { endpoints.authenticationmanager(authenticationmanager) .urdetailsrvice(urdetailsrvice) .tokenstore(jwttokenstore()) //设置jwttoken为tokenstore .accesstokenconverter(jwtaccesstokenconverter());//设置access_token转换器 } /** * jwt访问token转换器 */ @bean public jwtaccesstokenconverter jwtaccesstokenconverter(){ jwtaccesstokenconverter converter = new jwtaccesstokenconverter(); converter.tsigningkey("my-sign-key"); //资源服务器需要配置此选项方能解密jwt的token return converter; } /** * jwt的token存储对象 */ @bean public jwttokenstore jwttokenstore(){ return new jwttokenstore(jwtaccesstokenconverter()); }}
这里主要是在configure(authorizationrverendpointsconfigurer endpoints)
授权服务的端点配置中加入jwt的tokenstore和access_token的转换器,以及这二者的声明bean方法
这里使用的是默认对称mac算法,即加密解密使用相同的密钥
启动类就不说了,开启@springbootapplicatin的main方法
资源服务器主要就一个资源配置类
@configuration@enableresourcerverpublic class resourceconfig extends resourcerverconfigureradapter { @bean public passwordencoder passwordencoder() { return new bcryptpasswordencoder(); } @override public void configure(httpcurity http) throws exception { //设置创建ssion策略 http.ssionmanagement().ssioncreationpolicy(ssioncreationpolicy.if_required); //@formatter:off //所有请求必须授权 http.authorizerequests() .anyrequest().authenticated(); //@formatter:on } @override public void configure(resourcervercurityconfigurer resources) { //@formatter:off //如不需要限制资源id,请在授权配置处去除resourceids的配置 resources.resourceid("resource1") .tokenstore(jwttokenstore()); //@formatter:on } /** * jwt访问token转换器 */ @bean public jwtaccesstokenconverter jwtaccesstokenconverter(){ jwtaccesstokenconverter converter = new jwtaccesstokenconverter(); converter.tsigningkey("my-sign-key"); //与授权服务器相同的signingkey return converter; } /** * jwt的token存储对象 */ @bean public jwttokenstore jwttokenstore(){ return new jwttokenstore(jwtaccesstokenconverter()); }}
配置jwt的tokenstore和accesstokenconverter与授权服器相世界地图中文版高清同,添加启动类完成配置
本部分基于对称加密部分,仅展示需要修改的部分
首先使用keytool生成jks (java key store) 密钥,按提示输入姓氏等信息
keytool -genkeypair -alias hellxz-jwt -validity 3650 -keyalg rsa -keypass hellxztest -keystore hellxz-jwt.jks -storepass hellxztest
生成的私钥文件会在当前目录,把hellxz-jwt.jks复制到授权服务器的resources目录下
授权服务器需修改jwtaccesstokenconverter()
@bean public jwtaccesstokenconverter jwtaccesstokenconverter(){ jwtaccesstokenconverter converter = new jwtaccesstokenconverter(); keystorekeyfactory storekeyfactory = new keystorekeyfactory( new classpathresource("hellxz-jwt.jks"), "hellxztest".tochararray()); converter.tkeypair(storekeyfactory.getkeypair("hellxz-jwt")); return converter; }
在hellxz-jwt.jks同目录下,执行命令生成公钥
keytool -list -rfc –keystore hellxz-jw适合婴儿听的音乐t.jks | openssl x509 -inform pem -pubkey
输入密钥库口令: hellxztest
—–begin public key—–
miibijanbgkqhkig9w0baqefaaocaq8amiibcgkcaqeaxu7zulfuvbxmzd28xwm4
ul5e9yfrtolgwkhlnllp904/gbiwboz4tcbcnq3vxlgbn9voqfp1p5c7frgz95ui
7shkckgsffgl2raqsplmdcln/adfsxmpf06rvikggce9tr0q0ioncan+b/lark4t
au76qsqwn9mlxlznvfczclzozsfdnju+1jubzqt6fepwqalbuvydv0zcudg8ikn1
l9d0m1tss美式足球电影akpitru2yeuguji+79ury7y8bclex6d4ctl9tqahl5g32gojec0s2y+
0bqequsv1nut9kijt9kiova+q7o2t8ohuqqt9le7kvmii4gsx5vsnvvzage2uglh
zqidaqab
—–end public key—–
—–begin certificate—–
miidutccajmgawibagieepedczanbgkqhkig9w0baqsfadbzmqswcqydvqqgewjd
tjeqma4ga1uecbmhymvpamluzzeqma4ga1uebxmhymvpamluzzekmagga1uechmb
mdekmagga1uecxmbmdeomawga1ueaxmfemhhbmcwhhcnmtkxmje1mduyotm2whcn
mjkxmjeymduyotm2wjbzmqswcqydvqqgewjdtjeqma4ga1uecbmhymvpamluzzeq
ma4ga1uebxmhymvpamluzzekmagga1uechmbmdekmagga1uecxmbmdeomawga1ue
axmfemhhbmcwggeima0gcsqgsib3dqebaquaa4ibdwawggekaoibaqdftvo6uvru
fezkpbzhazi6xl73iwtogubyoeu0uwn3tj8zujyghni1wfw2rdxesye31u6p8/u/
klt9gdp3lqjtkeoiqcwuuyvascqymuwmku39p1+zgakxtqtuiqabx721hrdsi41x
o35v+ucsrhmc7vpcxdcf0wtexodv9znyvk5lj8m2o77um4hoq3p8q9apqufrvh1x
tmjqmbykq3wx0psbw1jjoqmjottbirqzsol7v1svltjwekurfp3gjox1nacevmdf
yagkrzrlbl7rup6psy/wds30qilp2si68d5dujzpw4e6pbp2v7us+yilibjfm9i2
+9lqatzscwhnagmbaagjitafmb0ga1uddgqwbbqf96rk7n0xufnvtjuh9td9ixza
6zanbgkqhkig9w0baqsfaaocaqeaumzwzjhej6+4tggodqkq5l5rbtoubesxa1ue
s9ia4m/jnznvcxje0ny47yvzbcikisyalswgoomj1pijxempggxvmiuijpapgg+4
sthzisxkzx0ru8irjtapaglmi74ai6s73ltbske9gepgwwnbtduzousisnt1oj0j
ehfhdpuzxc36nedfrbobxw4w3qhstlktn2wjm1nlv96nfkmqjhqjhhkt6ihe7hmg
qwxznswaqv9gjndkzt5teqwnkt6h7r1nx5ojkj0kn1dzy0o3rddd5e0kdkkmtwoh
3dejh6uvtt/dw/drzjlbyndepp6hygqu2dw5jg5uihuzfhnjea==
—–end certificate—–
复制公钥部分到public.cert放到资源服务器的resources目录
—–begin public key—–
miibijanbgkqhkig9w0baqefaaocaq8amiibcgkcaqeaxu7zulfuvbxmzd28xwm4
ul5e9yfrtolgwkhlnllp904/gbiwboz4tcbcnq3vxlgbn9voqfp1p5c7frgz95ui
7shkckgsffgl2raqsplmdcln/adfsxmpf06rvikggce9tr0q0ioncan+b/lark4t
au76qsqwn9mlxlznvfczclzozsfdnju+1jubzqt6fepwqalbuvydv0zcudg8ikn1
l9d0m1tssakpitru2yeuguji+79ury7y8bclex6d4ctl9tqahl5g32gojec0s2y+
0bqequsv1nut9kijt9kiova+q7o2t8ohuqqt9le7kvmii4gsx5vsnvvzage2uglh
zqidaqab
—–end public key—–
修改资源服务器jwtaccesstokenconverter()方法
@bean public jwtaccesstokenconverter jwtaccesstokenconverter(){ jwtaccesstokenconverter converter = new jwtaccesstokenconverter(); resource resource = new classpathresource("public.cert"); string publickey; try { publickey = new string(filecopyutils.copytobytearray(resource.getinputstream())); } catch (ioexception e) { throw new runtimeexception(e); } converter.tverifierkey(publickey); return converter; }
发送post请求http://localhost:8080/oauth/token?urname=hellxz&password=xyz&scope=read_ur_info&grant_type=password
返回结果
带token访问资源服务器
另外使用jwt应设置尽量短的过期时间,因为jwt的token无法手动revoke,只能等待其到达过期时间失效
到此这篇关于使用jwt作为spring curity oauth2的token存储的文章就介绍到这了,更多相关spring curity oauth2 token存储内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
本文发布于:2023-04-04 05:17:48,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/09553e6b888294c2226ca097e3c1b14e.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:使用JWT作为Spring Security OAuth2的token存储问题.doc
本文 PDF 下载地址:使用JWT作为Spring Security OAuth2的token存储问题.pdf
留言与评论(共有 0 条评论) |