写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!如果我的博客对你有帮助,欢迎进行评论✏️✏️、点赞👍👍、收藏⭐️⭐️,满足一下我的虚荣心💖🙏🙏🙏 。
上一篇介绍了jwt相关的概念及与oauth2和session的区别等,现在记录一下jwt令牌的使用姿势,暂时先使用对称加密的方式,之后再完善使用非对称加密的方式。本篇代码基于第七篇: Spring Security OAuth2四种授权模式总结(七)
目录
修改Token格式
@Configuration
public class TokenConfig {
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("abc123");
return converter;
}
}
授权服务器
在授权服务中注入上面的TokenStore,并修改令牌管理器增加jwt相关的配置
@Autowired
private JwtAccessTokenConverter accessTokenConverter;
@Bean
public AuthorizationServerTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
//tokenServices.setClientDetailsService(clientDetailsService);
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenStore(tokenStore);
// 有效期10秒
tokenServices.setAccessTokenValiditySeconds(10);
// 刷新令牌默认有效期3天
tokenServices.setRefreshTokenValiditySeconds(10);
// 配置token增强使用jwt
TokenEnhancerChain chain = new TokenEnhancerChain();
chain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
tokenServices.setTokenEnhancer(chain);
return tokenServices;
}
获取jwt令牌
获取token,如下:
localhost:9005/oauth/token?client_id=dev-client&client_secret=123456&grant_type=client_credentials
返回如下:
注意:这里把授权服务的 endpoints.authenticationManager(authenticationManager) 已经注释掉了,获取token的时候需要使用客户端模式,如果使用password模式肯定会报错了,错误如下:
{
"error": "unsupported_grant_type",
"error_description": "Unsupported grant type: password"
}
另外,上面客户端模式是不返回refresh_token的。
校验jwt令牌
可以使用 /oauth/check_token 端点校验令牌的有效性,并查询令牌内容,前提是授权服务中开放次端点,检查下AuthorizationServerSecurityConfigurer中是否有如下配置:
security.tokenKeyAccess("permitAll()");
首先,我们获取一个jwt令牌,请求如下:
localhost:9005/oauth/token?client_id=dev-client&client_secret=123456&grant_type=client_credentials
然后,执行如下请求:
此处的value值为上一步获取的access_token,返回结果如下:
{
"aud": [
"product-service"
],
"scope": [
"all"
],
"active": true,
"exp": 1676622513,
"jti": "0fc565f1-ac49-4ca9-9aaa-1befb2cb71e6",
"client_id": "dev-client"
}
自定义Payload
自定义token携带信息很简单,主要步骤就是自定义TokenEnhancer,然后将自定义的TokenEnhancer加入到TokenEnhancerChain中,最后设置到端点中endpoints.tokenEnhancer(tokenEnhancerChain) 。
首先,授权服务器新增TokenEnhancer实现类,代码如下:
@Component
public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
Map<String, Object> additionalInfo = new HashMap<>(16);
additionalInfo.put("userid", "123");
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}
然后,将tokenEnhancer注入,追加到TokenEnhancerChain中,并设置到endponits,代码如下:
@Autowired
private CustomTokenEnhancer tokenEnhancer;
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer, accessTokenConverter()));
endpoints.tokenEnhancer(tokenEnhancerChain);
最后,重启授权服务uaa,再次获取token,结果如下:
生成的这个token的payload载荷中也是有这个userid的,可以从如下网站验证一下: