当前位置:   article > 正文

springsecurity+oauth2.0分布式认证授权案例 JWT令牌服务配置5_springsecurity+oauth2【授权码模式】+增强jwt

springsecurity+oauth2【授权码模式】+增强jwt

jwt的概念

1.1 jwt作用

JSON Web Token JWT )是一个开放的行业标准( RFC 7519 ),它定义了一种简介的、自包含的协议格式,用于 在通信双方传递json对象 传递的信息经过数字签名可以被验证和信任 JWT 可以使用 HMAC算法或使用RSA的公钥/私钥对来签名,防止被篡改。

1.2 jwt可以的解决问题

当资源服务和授权服务不在一起时资源服务使用 RemoteTokenServices 远程请求授权 服务验证token ,如果访问量较大将会影响系统的性能 。
解决上边问题:
令牌采 用JWT格式 即可解决上边的问题,用户认证通过会得到一个 JWT 令牌, JWT令牌中已经包括了用户相关的信 息 客户端只需要携带JWT访问资源服务 资源服务根据事先约定的算法自行完成令牌校验 无需次都请求认证服务完成授权

1.3 jwt的特点

1 jwt基于json,非常方便解析
2 )可以在令牌中自定义丰富的内容,易扩展。
3 通过非对称加密算法及数字签名技术 JWT防止篡改 ,安全性高。
4 )资源服 务使用JWT可不依赖认证服务即可完成授权
缺点:
1) JWT 令牌较长,占存储空间比较大。

1.4 JWT令牌结构

JWT 令牌由三部分组成,每部分中间使用点( . )分隔,比如: xxxxx.yyyyy.zzzzz

1.4.1 头部

头部包括令牌的类型(即 JWT )及使用的哈希算法(如 HMAC SHA256 RSA

 1.4.2 payload

第二部分是负载,内容也是 一个json对象,它是存放有效信息的地方 ,它可以存放 jwt 提供的现成字段,比 如:iss (签发者) ,exp (过期时间戳) , sub (面向的用户)等,也可自定义字段。

  1.4.3  signature

第三部分是签名,此部分用于防止 jwt 内容被篡改。
这个部分使用 base64url 将前两部分进行编码,编码后使用点( . )连接组成字符串,最后使用 header 中声明 签名算法进行签名。

二 jwt的配置

2.1 在认证uaa中配置jwt令牌

1.在spt-ds-uaa-server认证工程中,将前面章节使用的基于内存的令牌注释掉,使用jwt令牌

2.代码

  1. package com.ljf.springsecurity.oauth.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.security.oauth2.provider.token.TokenStore;
  5. import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
  6. import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
  7. import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
  8. /**
  9. * @ClassName: TokenConfig
  10. * @Description: TODO
  11. * @Author: liujianfu
  12. * @Date: 2021/08/29 12:49:39 
  13. * @Version: V1.0
  14. **/
  15. @Configuration
  16. public class TokenConfig {
  17. private String SIGNING_KEY = "uaa123";
  18. @Bean
  19. public TokenStore tokenStore() {
  20. //JWT令牌存储方案
  21. return new JwtTokenStore(accessTokenConverter());
  22. }
  23. @Bean
  24. public JwtAccessTokenConverter accessTokenConverter() {
  25. JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
  26. converter.setSigningKey(SIGNING_KEY); //对称秘钥,资源服务器使用该秘钥来验证
  27. return converter;
  28. }
  29. /**
  30. @Bean
  31. public TokenStore tokenStore() {
  32. //使用内存存储令牌(普通令牌)
  33. return new InMemoryTokenStore();
  34. }
  35. **/
  36. }

2.2 在认证服务配置类中使用jwt令牌

2.具体代码

  1. package com.ljf.springsecurity.oauth.config;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.http.HttpMethod;
  6. import org.springframework.security.authentication.AuthenticationManager;
  7. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  8. import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
  9. import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
  10. import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
  11. import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
  12. import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
  13. import org.springframework.security.oauth2.provider.ClientDetailsService;
  14. import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
  15. import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
  16. import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
  17. import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
  18. import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
  19. import org.springframework.security.oauth2.provider.token.TokenStore;
  20. import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
  21. import java.util.Arrays;
  22. /**
  23. * @ClassName: AuthorizationServer
  24. * @Description: TODO
  25. * @Author: liujianfu
  26. * @Date: 2021/08/29 12:46:21 
  27. * @Version: V1.0
  28. **/
  29. @Configuration
  30. @EnableAuthorizationServer
  31. public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
  32. @Autowired
  33. private TokenStore tokenStore;
  34. @Autowired
  35. private ClientDetailsService clientDetailsService;
  36. @Autowired
  37. private AuthorizationCodeServices authorizationCodeServices;
  38. @Autowired
  39. private AuthenticationManager authenticationManager;
  40. @Autowired
  41. private JwtAccessTokenConverter accessTokenConverter;
  42. //step1:客户端详情服务
  43. @Override
  44. public void configure(ClientDetailsServiceConfigurer clients)
  45. throws Exception {
  46. clients.inMemory()// 使用in-memory存储
  47. .withClient("c1")// client_id
  48. .secret(new BCryptPasswordEncoder().encode("secret"))//客户端密钥
  49. .resourceIds("res1")//资源列表
  50. .authorizedGrantTypes("authorization_code", "password","client_credentials","implicit","refresh_token")// 该client允许的授权类型authorization_code,password,refresh_token,implicit,client_credentials
  51. .scopes("all")// 允许的授权范围
  52. .autoApprove(false)//false跳转到授权页面
  53. //加上验证回调地址
  54. .redirectUris("http://www.baidu.com");
  55. }
  56. //step2; 令牌管理服务
  57. @Bean
  58. public AuthorizationServerTokenServices tokenService() {
  59. DefaultTokenServices service=new DefaultTokenServices();
  60. service.setClientDetailsService(clientDetailsService);//客户端详情服务
  61. service.setSupportRefreshToken(true);//支持刷新令牌
  62. service.setTokenStore(tokenStore);//令牌存储策略
  63. //令牌增强
  64. TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
  65. tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
  66. service.setTokenEnhancer(tokenEnhancerChain);
  67. service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
  68. service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3
  69. return service;
  70. }
  71. //step3: 设置授权码模式的授权码如何存取,暂时采用内存方式
  72. @Bean
  73. public AuthorizationCodeServices authorizationCodeServices() {
  74. return new InMemoryAuthorizationCodeServices();
  75. }
  76. //step4: 令牌服务端点
  77. @Override
  78. public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
  79. endpoints
  80. .authenticationManager(authenticationManager)//认证管理器
  81. .authorizationCodeServices(authorizationCodeServices)//授权码服务
  82. .tokenServices(tokenService())//令牌管理服务
  83. .allowedTokenEndpointRequestMethods(HttpMethod.POST);
  84. }
  85. //step5: 令牌安全约束
  86. @Override
  87. public void configure(AuthorizationServerSecurityConfigurer security){
  88. security
  89. .tokenKeyAccess("permitAll()") //oauth/token_key是公开
  90. .checkTokenAccess("permitAll()") //oauth/check_token公开
  91. .allowFormAuthenticationForClients() //表单认证(申请令牌)
  92. ;
  93. }
  94. }

2.3  生成jwt令牌

1.启动认证服务

2.使用密码模式生成jwt令牌:jwt令牌的字符串包含了用户信息和权限等信息

http://localhost:53020/uaa/oauth/token? client_id=c1&client_secret=secret&grant_type=password&username=shangsan&password=123

 2.4  验证jwt令牌信息

 2.5 在order资源服务中校验jwt令牌

在上一章节中,在资源服务拿到token令牌后,需要远程调用认证服务,解析token是否正确有效

那么现在使用jwt的token令牌,则不需要再调用认证服务了,直接解析jwt的token串进行校验

资源服务需要和授权服务拥有一致的签字、令牌服务等:
1、将授权服务中的TokenConfifig类拷贝到资源 服务中

2、屏蔽资源 服务原来的令牌服务类
3.代码实现类型tokenconfig:
  1. package com.ljf.springsecurity.oauth.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.security.oauth2.provider.token.TokenStore;
  5. import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
  6. import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
  7. /**
  8. * @ClassName: TokenConfig
  9. * @Description: TODO
  10. * @Author: liujianfu
  11. * @Date: 2021/08/29 12:49:39 
  12. * @Version: V1.0
  13. **/
  14. @Configuration
  15. public class TokenConfig {
  16. private String SIGNING_KEY = "uaa123";
  17. @Bean
  18. public TokenStore tokenStore() {
  19. //JWT令牌存储方案
  20. return new JwtTokenStore(accessTokenConverter());
  21. }
  22. @Bean
  23. public JwtAccessTokenConverter accessTokenConverter() {
  24. JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
  25. converter.setSigningKey(SIGNING_KEY); //对称秘钥,资源服务器使用该秘钥来验证
  26. return converter;
  27. }
  28. /**
  29. @Bean
  30. public TokenStore tokenStore() {
  31. //使用内存存储令牌(普通令牌)
  32. return new InMemoryTokenStore();
  33. }
  34. **/
  35. }
4.资源配置类的操作:ResouceServerConfig
  1. package com.ljf.springsecurity.oauth.config;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  6. import org.springframework.security.config.http.SessionCreationPolicy;
  7. import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
  8. import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
  9. import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
  10. import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
  11. import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
  12. import org.springframework.security.oauth2.provider.token.TokenStore;
  13. /**
  14. * @author Administrator
  15. * @version 1.0
  16. **/
  17. @Configuration
  18. @EnableResourceServer
  19. public class ResouceServerConfig extends ResourceServerConfigurerAdapter {
  20. @Autowired
  21. TokenStore tokenStore;
  22. public static final String RESOURCE_ID = "res1";//和认证服务器中的安全配置文件设置要一致
  23. @Override
  24. public void configure(ResourceServerSecurityConfigurer resources) {
  25. resources.resourceId(RESOURCE_ID)//资源 id
  26. .tokenStore(tokenStore)
  27. // .tokenServices(tokenService())//验证令牌的服务
  28. .stateless(true);
  29. }
  30. @Override
  31. public void configure(HttpSecurity http) throws Exception {
  32. http
  33. .authorizeRequests()
  34. .antMatchers("/**").access("#oauth2.hasScope('all')")
  35. .and().csrf().disable()
  36. .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  37. }
  38. //资源服务令牌解析服务
  39. /**
  40. @Bean
  41. public ResourceServerTokenServices tokenService() {
  42. //使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secret
  43. RemoteTokenServices service=new RemoteTokenServices();
  44. service.setCheckTokenEndpointUrl("http://localhost:53020/uaa/oauth/check_token");
  45. service.setClientId("c1");
  46. service.setClientSecret("secret");
  47. return service;
  48. }
  49. **/
  50. }

 2.6 测试请求资源

1 )申请 jwt 令牌
2 )使用令牌请求资源
1.启动资源服务

2.访问资源
将前面得到的令牌  :
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzMSJdLCJ1c2VyX25hbWUiOiJiZWlqaW5nIiwic2NvcGUiOlsiYWxsIl0sImV4cCI6MTYzMDQyNDE1NCwiYXV0aG9yaXRpZXMiOlsicDEiLCJwMyJdLCJqdGkiOiJkMWQyN2NhMC1mMzMyLTQ4YzktYmY1NS1mM2NlNjFmMGY5MjYiLCJjbGllbnRfaWQiOiJjMSJ9.M-ZhEVNE6StpixS8r5LJylLrWUCgg7pCJwIkKIhPjMs
复制到Bearer 后面,进行请求

 2.7 将请求资源的角色改为其他

在controller中将请求资源的方法的角色改为其他,就是请求用户不具备的角色。

beijing 用户的角色为p1,p3,而现在访问此方法必须为p5角色才行。

 执行访问的结果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/84415
推荐阅读
相关标签
  

闽ICP备14008679号