Spring Security 5中TokenStore、TokenServices等组件的替代方案咨询
Spring Security OAuth2 到 Spring Security 5+ 资源服务器迁移方案
针对你在Kotlin项目中从Spring Boot 2.3升级到2.7.7时遇到的OAuth2资源服务器组件替换问题,以下是具体的迁移实现:
核心组件替换说明
- TokenStore/JwkTokenStore:Spring Security 5+的OAuth2资源服务器不再需要TokenStore,直接通过
JwtDecoder解析JWK格式的令牌,无需存储令牌。 - DefaultTokenServices:无状态JWT验证模式下无需令牌服务,令牌的有效性、签名验证直接由
JwtDecoder完成。 - JwtAccessTokenConverter/MyTokenConverter:替换为
JwtAuthenticationConverter,用于将JWT中的Claims转换为Authentication对象。
迁移后的配置代码
1. 资源服务器配置类
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) class ResourceServerConfig : WebSecurityConfigurerAdapter() { @Value("...") private val claimAud: String? = null @Value("...") private val urlJwk: String? = null override fun configure(http: HttpSecurity) { http .anonymous().and() .cors(withDefaults()) .authorizeRequests() .mvcMatchers(BASE_PATH_PATTERN).permitAll() .mvcMatchers(API_PATH_PATTERN).permitAll() .mvcMatchers(ADMIN_PATH_PATTERN).authenticated() .and() .oauth2ResourceServer() // 启用OAuth2资源服务器 .jwt() // 使用JWT验证 .decoder(jwtDecoder()) .jwtAuthenticationConverter(jwtAuthenticationConverter()) } @Bean fun jwtDecoder(): JwtDecoder { logger.info("JWK settings resource config: $urlJwk") // 基于JWK集合URI创建JWT解码器,替代原JwkTokenStore val decoder = NimbusJwtDecoder.withJwkSetUri(urlJwk).build() // 验证audience(对应原resourceId配置) var validator = JwtValidators.createDefaultWithIssuer("") // 若有issuer可填入,否则留空 if (!claimAud.isNullOrEmpty()) { validator = validator.and(AudienceValidator(claimAud)) } decoder.setJwtValidator(validator) return decoder } @Bean fun jwtAuthenticationConverter(): JwtAuthenticationConverter { val converter = JwtAuthenticationConverter() // 设置自定义权限转换器,替代原MyTokenConverter的权限解析逻辑 converter.setJwtGrantedAuthoritiesConverter(CustomJwtGrantedAuthoritiesConverter()) // 自定义转换逻辑:将JWT Claims存入Authentication details return converter.apply { this.authenticationConverter = { jwt -> val authentication = super.convert(jwt) authentication?.details = jwt.claims authentication } } } @Bean fun securityEvaluationContextExtension(): SecurityEvaluationContextExtension { return SecurityEvaluationContextExtension() } // 自定义Audience验证器,对应原resourceId的校验逻辑 private class AudienceValidator(private val expectedAudience: String) : OAuth2TokenValidator<Jwt> { override fun validate(token: Jwt): OAuth2TokenValidatorResult { val errors = mutableListOf<OAuth2Error>() if (!token.audience.contains(expectedAudience)) { errors.add(OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN, "Invalid audience", null)) } return OAuth2TokenValidatorResult.failure(errors) } } }
2. 自定义权限转换器(替代原MyTokenConverter的权限解析)
如果原MyTokenConverter还负责从Claims解析权限,需要单独实现JwtGrantedAuthoritiesConverter:
@Component class CustomJwtGrantedAuthoritiesConverter : JwtGrantedAuthoritiesConverter() { // 重写权限解析逻辑,对应原DefaultAccessTokenConverter的权限处理 override fun convert(jwt: Jwt): Collection<GrantedAuthority> { // 这里可根据你的JWT权限字段自定义解析,比如从"authorities"或"roles"字段获取 val authorities = super.convert(jwt) // 示例:给权限添加ROLE_前缀(根据业务需求调整) return authorities.map { SimpleGrantedAuthority("ROLE_${it.authority}") } } }
关键细节说明
- 原
ResourceServerSecurityConfigurer中的resourceId配置,通过AudienceValidator实现对JWT中aud字段的校验。 - 原
MyTokenConverter中将Claims存入Authentication details的逻辑,通过JwtAuthenticationConverter的自定义转换逻辑实现。 - 无需再配置
TokenStore和TokenServices,Spring Security 5+的OAuth2资源服务器采用无状态JWT验证,直接通过解码器完成令牌有效性验证。
内容的提问来源于stack exchange,提问作者laMariposa
相关产品推荐
相关产品推荐

