如何将Spring Security 2.x.x的resourceId迁移至5.7.x版本?
Spring Security 5.7.x 替代 ResourceServerConfigurerAdapter 的配置方案
Spring Security 5.7+ 移除了 ResourceServerConfigurerAdapter,改用基于 SecurityFilterChain 的函数式配置。针对你原来的 resourceId 和 tokenServices 配置需求,可按以下方式适配:
核心配置思路
- 用
@EnableWebSecurity+SecurityFilterChainBean 替代原适配器类 resourceId对应 OAuth2 令牌中的audience(aud)声明,需自定义校验逻辑实现原功能tokenServices需适配为新版的JwtDecoder(JWT 令牌场景)或OpaqueTokenIntrospector(不透明令牌场景)
代码示例
场景1:JWT 令牌配置
@Configuration @EnableWebSecurity public class SecurityConfig { private final String resourceIds; private final JwtDecoder jwtDecoder; public SecurityConfig(@Value("${oauth2.resource-id}") String resourceIds, JwtDecoder jwtDecoder) { this.resourceIds = resourceIds; this.jwtDecoder = jwtDecoder; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2 .jwt(jwt -> jwt .decoder(jwtDecoder) .jwtAuthenticationConverter(customJwtConverter()) ) ); return http.build(); } // 自定义JWT转换器,添加resourceId(audience)校验 private JwtAuthenticationConverter customJwtConverter() { return new JwtAuthenticationConverter() { @Override protected AbstractAuthenticationToken convert(Jwt jwt) { // 校验令牌audience是否包含当前服务的resourceId Collection<String> audiences = jwt.getAudience(); if (!audiences.contains(resourceIds)) { throw new OAuth2AuthenticationException( new OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN, "令牌受众不匹配", null) ); } // 保留默认权限转换逻辑 JwtGrantedAuthoritiesConverter authoritiesConverter = new JwtGrantedAuthoritiesConverter(); Collection<GrantedAuthority> authorities = authoritiesConverter.convert(jwt); return new JwtAuthenticationToken(jwt, authorities); } }; } }
场景2:不透明令牌(Opaque Token)配置
@Configuration @EnableWebSecurity public class SecurityConfig { private final String resourceIds; private final String introspectionUri; private final String clientId; private final String clientSecret; public SecurityConfig(@Value("${oauth2.resource-id}") String resourceIds, @Value("${oauth2.introspection-uri}") String introspectionUri, @Value("${oauth2.client-id}") String clientId, @Value("${oauth2.client-secret}") String clientSecret) { this.resourceIds = resourceIds; this.introspectionUri = introspectionUri; this.clientId = clientId; this.clientSecret = clientSecret; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2 .opaqueToken(token -> token.introspector(customOpaqueTokenIntrospector())) ); return http.build(); } // 自定义令牌自省器,添加resourceId校验 private OpaqueTokenIntrospector customOpaqueTokenIntrospector() { return new NimbusOpaqueTokenIntrospector(introspectionUri, clientId, clientSecret) { @Override public OAuth2AuthenticatedPrincipal introspect(String token) { OAuth2AuthenticatedPrincipal principal = super.introspect(token); // 从自省结果中获取audience字段并校验 Collection<String> audiences = principal.getAttribute(OAuth2IntrospectionClaimNames.AUD); if (!audiences.contains(resourceIds)) { throw new OAuth2AuthenticationException( new OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN, "令牌受众不匹配", null) ); } return principal; } }; } }
关键说明
- 若你原有自定义
tokenServices,可将其逻辑封装到JwtDecoder或OpaqueTokenIntrospector的自定义实现中 resourceId的校验本质是验证令牌的受众是否与当前服务匹配,这是 OAuth2 资源服务的核心安全逻辑之一
内容的提问来源于stack exchange,提问作者saurabh Dubey
相关产品推荐
相关产品推荐

