Spring Security Oauth2整合JWT
整合JWT
在之前的spring security Oauth2的代码基础上修改[详见之前的文章]
引入依赖
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.0.9.RELEASE</version>
</dependency>
添加配置文件JwtTokenStoreConfig.java
@Configuration
public class JwtTokenStoreConfig {
@Bean
public TokenStore jwtTokenStore(){
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter accessTokenConverter = new
JwtAccessTokenConverter();
//配置JWT使用的秘钥
accessTokenConverter.setSigningKey("123123");
return accessTokenConverter;
}
}
在授权服务器配置中指定令牌的存储策略为JWT
@Autowired
private UserService userService;
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)throws Exception{
endpoints.authenticationManager(authenticationManagerBean) //使用密码模式需要配置
.tokenStore(tokenStore) //指定token存储到redis
.accessTokenConverter(jwtAccessTokenConverter)
.reuseRefreshTokens(false) //refresh_token是否重复使用
.userDetailsService(userService) //刷新令牌授权包含对用户信息的检查
.allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST); //支持GET,POST请求
}
用密码模式测试
发现获取到的令牌已经变成了JWT令牌,将access_token拿到https://jwt.io/ 网站上去解析下可以获得其中内容。
扩展JWT中的存储内容
有时候我们需要扩展JWT中存储的内容,这里我们在JWT中扩展一个 key为enhance,value为enhance info 的数据。 继承TokenEnhancer实现一个JWT内容增强器
public class JwtTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken,
OAuth2Authentication authentication) {
Map<String, Object> info = new HashMap<>();
info.put("enhance", "enhance info");
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);
return accessToken;
}
}
创建一个JwtTokenEnhancer实例
@Bean
public JwtTokenEnhancer jwtTokenEnhancer() {
return new JwtTokenEnhancer();
}
在授权服务器配置中配置JWT的内容增强器
@Autowired
private JwtTokenEnhancer jwtTokenEnhancer;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
//配置JWT的内容增强器
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
List<TokenEnhancer> delegates = new ArrayList<>();
delegates.add(jwtTokenEnhancer);
delegates.add(jwtAccessTokenConverter);
enhancerChain.setTokenEnhancers(delegates);
endpoints.authenticationManager(authenticationManagerBean) //使用密码模式需要配置
.tokenStore(tokenStore) //配置存储令牌策略
.accessTokenConverter(jwtAccessTokenConverter)
.tokenEnhancer(enhancerChain) //配置tokenEnhancer
.reuseRefreshTokens(false) //refresh_token是否重复使用
.userDetailsService(userService) //刷新令牌授权包含对用户信息的检查
.allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST); //支持GET,POST请求
}
运行项目后使用密码模式来获取令牌,之后对令牌进行解析,发现已经包含扩展的内容。
解析JWT
添加依赖
<!--JWT依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
修改UserController类,使用jjwt工具类来解析Authorization头中存储的JWT内容
@GetMapping("/getCurrentUser")
public Object getCurrentUser(Authentication authentication,
HttpServletRequest request) {
String header = request.getHeader("Authorization");
String token = null;
if(header!=null){
token = header.substring(header.indexOf("bearer") + 7);
}else {
token = request.getParameter("access_token");
}
return Jwts.parser()
.setSigningKey("123123".getBytes(StandardCharsets.UTF_8))
.parseClaimsJws(token)
.getBody();
}
将令牌放入Authorization头中,访问如下地址获取信息: http://localhost:8080/user/getCurrentUser
刷新令牌
http://localhost:8080/oauth/token?grant_type=refresh_token&client_id=client&client_secret=123123&refresh_token=[refresh_token值]