You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Spring Security 2.x.x的resourceId迁移至5.7.x版本?

Spring Security 5.7.x 替代 ResourceServerConfigurerAdapter 的配置方案

Spring Security 5.7+ 移除了 ResourceServerConfigurerAdapter,改用基于 SecurityFilterChain 的函数式配置。针对你原来的 resourceId 和 tokenServices 配置需求,可按以下方式适配:

核心配置思路

  1. 用 @EnableWebSecurity + SecurityFilterChain Bean 替代原适配器类
  2. resourceId 对应 OAuth2 令牌中的 audience(aud)声明,需自定义校验逻辑实现原功能
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 20:34:55