在阅读本文前你至少要知道怎么去搭建一个简单的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完成后,我们需要做一些什么嘞
- 定义TokenService服务,将自定义LwTokenEnhancer放入到TokenService中,
- 将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后,就可以将用户信息在认证的时候直接返回给前端