spring cloud oauth 集成 JWT 之 token 增强

1,305 阅读2分钟

在阅读本文前你至少要知道怎么去搭建一个简单的oauth2认证服务器

token增强是什么

其实token增强就是我们可以基于token去做一些额外的操作,比如说我们需要在用户访问认证授权端点的时候,将用户信息一并返回给前端

了解过spring cloud oauth2 生成token流程的小伙伴应该都知道,在生成token的时候,有一段代码是判断TokenEnhancer是否为空,不为空则调用TokenEnhancer去增强token

如果你不了解spring cloud oauth2 生成token流程,可以看看我的Spring cloud oauth token生成源码解析

下面是创建token流程中的一小部分代码,我们需要关注的就是最后一行

private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) {
   DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString());
   int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request());
   if (validitySeconds > 0) {
      token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L)));
   }
   token.setRefreshToken(refreshToken);
   token.setScope(authentication.getOAuth2Request().getScope());

//这一步就是判断TokenEnhancer是否为空,不为空则对调用TokenEnhancer去增强token
   return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token;
}

如何自定义TokenEnhancer

  • 自定义LwTokenEnhancer实现TokenEnhancer接口,实现enhance方法
  • OAuth2Authentication对象中包含了前端请求参数,还有ClientDtails信息以及用户信息,我们通过oAuth2Authentication.getUserAuthentication方法获取到用户信息,然后将用户信息放入map中,最后传入token中
public class LwTokenEnhancer implements TokenEnhancer {


    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
        Authentication authentication = oAuth2Authentication.getUserAuthentication();

        final Map<String, Object> additionalInfo = new HashMap<>(8);
        additionalInfo.put(SecurityConstants.USER_INFO, authentication.getPrincipal());
        ((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(additionalInfo);
        return oAuth2AccessToken;
    }
}
  • 自定义的TokenEnhancer完成后,我们需要做一些什么嘞
    1. 定义TokenService服务,将自定义LwTokenEnhancer放入到TokenService中,
    2. 将tokenservice注入到令牌访问端点中
/**
 * 令牌访问端点
 *
 * @param endpoints
 */
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints.allowedTokenEndpointRequestMethods(HttpMethod.POST, HttpMethod.GET)
            .authenticationManager(authenticationManagerBean)
            .tokenServices(tokenServices())   //自定义令牌服务
            .tokenStore(tokenStore)  //自定义令牌存储策略
            .userDetailsService(lwUserDetailsService);  //自定义用户加载
}

/**
 * 令牌服务
 *
 * @param endpoints
 */
@Bean
public AuthorizationServerTokenServices tokenServices() {
    DefaultTokenServices services = new DefaultTokenServices();
    services.setSupportRefreshToken(true);//启用刷新token
    services.setClientDetailsService(clientDetailsService); //自定义客户端加载方式
    services.setAuthenticationManager(authenticationManagerBean);//注入认证管理器
    services.setTokenStore(tokenStore);//设置token存储策略

    TokenEnhancerChain chain = new TokenEnhancerChain();
    chain.setTokenEnhancers(Arrays.asList(lwTokenEnhancer,jwtAccessTokenConverter));//采用JWTtoken方式增强
    services.setTokenEnhancer(chain);//设置token增强器
    return services;
}

效果图

  • 未增强前访问/oauth/token端点,是不会返回UserInfo,
  • 通过实现自定义TokenEnhancer后,就可以将用户信息在认证的时候直接返回给前端 image.png