OAuth2.0 - 使用JWT替换Token 及 JWT内容增强

一、OAuth2.0

上篇文章我们讲解了OAuth2.0的几种认证模式,前面的讲解Token采用OAuth2.0自带的方式生成的Token,但是这种方式也存在这弊端,通过前面的测试我们发现,当资源服务和授权服务不在一起时资源服务使用RemoteTokenServices 远程请求授权服务验证token,如果访问量较大将会影响系统的性能 。

因此我们可以采用JWT生成令牌,用户认证通过会得到一个JWT令牌,JWT令牌中已经包括了用户相关的信息,客户端只需要携带JWT访问资源服务,资源服务根据事先约定的算法自行完成令牌校验,无需每次都请求认证服务完成授权。

下面是上篇文章的地址:

https://blog.csdn.net/qq_43692950/article/details/122523524

二、OAuth2.0整合JWT

本篇文章接着上篇文章的内容继续修改。

认证服务修改

先声明JWT的签名模式,这里采用对称加密的方式,密钥设为bxc123,这个在资源服务器也是这么修改:

@Configuration
public class TokenConfig {

    private String SIGNING_KEY = "bxc123";

    @Bean

    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());

    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(SIGNING_KEY); //对称秘钥,资源服务器使用该秘钥来验证
        return converter;
    }
}

下面还要修改AuthorizationServer配制类,主要AuthorizationServerTokenServices的配制,增加一个TokenEnhancerChain,将上面声明出的JwtAccessTokenConverter 配制进去。

@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private ClientDetailsService clientDetailsService;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private AuthorizationCodeServices authorizationCodeServices;

    @Autowired
    private JwtAccessTokenConverter accessTokenConverter;


    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()// 使用in‐memory存储
                .withClient("c1")// client_id
                .secret(new BCryptPasswordEncoder().encode("secret"))
                .resourceIds("res1")
                .authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")// 该client允许的授权类型 authorization_code,password,refresh_token,implicit,client_credentials
                .scopes("all")// 允许的授权范围
                .autoApprove(false) //加上验证回调地址
                .authorities("admin")
                .redirectUris("http://www.baidu.com");
    }

    //设置授权码模式的授权码如何存取,暂时采用内存方式
    @Bean
    public AuthorizationCodeServices authorizationCodeServices() {
        return new InMemoryAuthorizationCodeServices();
    }

    @Bean
    public AuthorizationServerTokenServices tokenService() {
        DefaultTokenServices service = new DefaultTokenServices();
        service.setClientDetailsService(clientDetailsService);
        service.setSupportRefreshToken(true);
        service.setTokenStore(tokenStore);
        //令牌增强
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> tokenEnhancers = new ArrayList<>();
        tokenEnhancers.add(accessTokenConverter);
        tokenEnhancerChain.setTokenEnhancers(tokenEnhancers);

        service.setTokenEnhancer(tokenEnhancerChain);
        service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
        service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
        return service;
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints
                .authenticationManager(authenticationManager)//认证管理器
                .authorizationCodeServices(authorizationCodeServices)//授权码服务
                .tokenServices(tokenService())//令牌管理服务
                .allowedTokenEndpointRequestMethods(HttpMethod.POST);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                .tokenKeyAccess("permitAll()")                    //oauth/token_key是公开
                .checkTokenAccess("permitAll()")                  //oauth/check_token公开
                .allowFormAuthenticationForClients();                //表单认证(申请令牌)
    }
}

重启auth认证服务。

资源服务修改

将上面写的TokenConfig类,覆盖到资源服务中,并修改ResouceServerConfig配制类,将前面写的远程访问认证服务校验令牌的逻辑,就可以去除掉了:

@Configuration
@EnableResourceServer
public class ResouceServerConfig extends ResourceServerConfigurerAdapter {
    public static final String RESOURCE_ID = "res1";

    @Autowired
    TokenStore tokenStore;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(RESOURCE_ID)//资源 id
                .tokenStore(tokenStore)
                .stateless(true);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/admin/**").hasAuthority("admin")
                .antMatchers("/common/**").hasAuthority("common")
                .and().csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
}

重启资源服务。

三、测试

使用密码模式登录系统获取token,可以看到获取的token已经是Jwt格式的了:
在这里插入图片描述

可以在一些Jwt在线解析的网站,解析下JWT:
在这里插入图片描述

下面使用token去访问资源服务接口:
在这里插入图片描述

四、JWT内容增强

上面可以看到JWT中默认放置了一些用户的信息,如果我们想要存放其他东西呢,只需使用DefaultOAuth2AccessTokensetAdditionalInformation方法,传递一个Map即可放置自定义的数据,其中可以获取用户的信息,也可以再查找其他自定义的信息放置,下面修改认证服务的AuthorizationServer配制类:

添加TokenEnhancer tokenEnhancer()方法:

 /**
  * JWT内容增强
  */
 @Bean
 public TokenEnhancer tokenEnhancer() {
     return (accessToken, authentication) -> {
         Map<String, Object> additionalInfo = new HashMap<>();
         User principal = (User)authentication.getUserAuthentication().getPrincipal();
         String username = principal.getUsername();
         additionalInfo.put("three","额外的内容!");
         ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
         return accessToken;
     };
 }

在构建TokenEnhancerChain对象时,将上面配制的设置进去:

@Bean
public AuthorizationServerTokenServices tokenService() {
    DefaultTokenServices service = new DefaultTokenServices();
    service.setClientDetailsService(clientDetailsService);
    service.setSupportRefreshToken(true);
    service.setTokenStore(tokenStore);
    //令牌增强
    TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
    List<TokenEnhancer> tokenEnhancers = new ArrayList<>();
    //内容增强
    tokenEnhancers.add(tokenEnhancer());
    tokenEnhancers.add(accessTokenConverter);
    tokenEnhancerChain.setTokenEnhancers(tokenEnhancers);

    service.setTokenEnhancer(tokenEnhancerChain);
    service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
    service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
    return service;
}

重启认证服务,再次登录,就可以看到增加的信息已经有了:
在这里插入图片描述
如果解析JWT,也可以看到内容:
在这里插入图片描述
在这里插入图片描述
喜欢的小伙伴可以关注我的个人微信公众号,获取更多学习资料!

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
OAuth2.0中,验证JWT Token的方式可以通过配置RemoteTokenServices来实现。当资源服务与授权服务不在同一处时,资源服务可以通过远程请求授权服务来验证JWT Token的有效性。这种方式可以避免资源服务直接解析和验证Token带来的性能压力。 具体实现步骤如下: 1. 在资源服务的配置文件中,配置RemoteTokenServices,设置授权服务的URL、ClientId和ClientSecret等信息。 2. 当资源服务收到请求时,从请求Header中获取JWT Token。 3. 调用RemoteTokenServices的方法,将JWT Token传递给授权服务进行验证。 4. 授权服务验证JWT Token的有效性,并返回验证结果给资源服务。如果Token有效,则资源服务可以继续处理请求;如果Token无效,则资源服务可以拒绝请求或者重新进行身份认证。 通过以上步骤,资源服务可以通过远程请求授权服务来验证JWT Token的有效性,从而确保接收到的Token是合法的。这种方式可以提高系统的性能,尤其在访问量较大时能够减轻资源服务的负担。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [OAuth2.0实战 使用JWT令牌认证](https://blog.csdn.net/Pastxu/article/details/124538331)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [OAuth2.0 - 使用JWT替换TokenJWT内容增强](https://blog.csdn.net/qq_43692950/article/details/122525414)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小毕超

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值