使用JWT(JSON Web Token)作为 Spring Security OAuth2 的 token 存储方案,可以避免服务器端存储 token 所带来的开销和管理复杂度,并且具有无状态、分布式、可扩展、自包含等优点,在实际开发中非常实用。下面是一份完整攻略:
1. 引入相关依赖
在 pom.xml 中添加 spring-security-jwt 依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2. 配置 JWT 相关 bean
在 Spring Security 的配置中添加以下 bean:
@Configuration
public class JwtTokenConfig {
@Value(“${jwt.secret}”)
private String secretKey;
@Value(“${jwt.expiration}”)
private long expiration;
@Bean
public JwtTokenUtil jwtTokenUtil() {
return new JwtTokenUtil(secretKey, expiration);
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(secretKey);
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
}
3. 自定义 JWT Token 增强器
使用自定义 JWT Token 增强器,可以在 JWT Token 中添加一些自定义内容,例如用户 ID,角色信息等等。具体实现如下:
@Configuration
public class JwtTokenEnhancerConfig implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
Map<String, Object> info = new HashMap<>();
// 在 JWT Token 中添加 userId
info.put(“userId”, ((User) authentication.getPrincipal()).getId());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);
return accessToken;
}
}
4. 配置 Spring Security OAuth2
在 Spring Security OAuth2 的配置中使用自定义的 JWT Token 存储方案和自定义的 JWT Token 增强器,具体实现如下:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
// 其他配置省略
@Autowired
private TokenStore tokenStore;
@Autowired
private JwtTokenEnhancer jwtTokenEnhancer;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore).tokenEnhancer(jwtTokenEnhancer)
.authenticationManager(authenticationManager).userDetailsService(userDetailsService);
super.configure(endpoints);
}
}
5. 示例
在访问受保护资源时,使用 JWT Token 进行身份验证:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@GetMapping("/info")
public ResponseEntity<UserInfo> getUserInfo(HttpServletRequest request) {
String authHeader = request.getHeader(“Authorization”);
String token = authHeader.substring(“Bearer “.length());
String username = jwtTokenUtil.getUsernameFromToken(token);
UserInfo userInfo = new UserInfo();
userInfo.setUsername(username);
// 其他信息
return ResponseEntity.ok(userInfo);
}
}
在授权服务器中,生成 JWT Token 并返回:
@PostMapping("/login")
public ResponseEntity<OAuth2AccessToken> login(@RequestParam String username,
@RequestParam String password, HttpServletResponse response) {
// 验证用户名密码省略
// 生成 JWT Token
Map<String, Object> claims = new HashMap<>();
claims.put(“sub”, username);
claims.put(“scopes”, Arrays.asList(“read”, “write”));
JwtBuilder jwtBuilder = Jwts.builder().setClaims(claims).setExpiration(new Date(System.currentTimeMillis() + 3600000))
.signWith(SignatureAlgorithm.HS512, secretKey.getBytes());
String accessToken = jwtBuilder.compact();
// 将 JWT Token 作为 OAuth2AccessToken 返回
DefaultOAuth2AccessToken oAuth2AccessToken = new DefaultOAuth2AccessToken(accessToken);
return ResponseEntity.ok(oAuth2AccessToken);
}
至此,使用 JWT 作为 Spring Security OAuth2 的 token 存储方案的完整攻略已经完成。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:使用JWT作为Spring Security OAuth2的token存储问题 - Python技术站