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

弃用WebSecurityConfigurerAdapter改用SecurityFilterChain遇配置错误求助

问题:Spring Security 升级到 SecurityFilterChain 后出现 Can't configure antMatchers after anyRequest 错误

背景

原应用有两个按优先级排序的Web安全配置:

  • 交互式/Web用户认证(优先级2)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
    // Needed for method access control via the @Secured annotation
    prePostEnabled = true,
    jsr250Enabled = true,
    securedEnabled = true
)
@Profile({"cognito"})
@Order(2)
public class CognitoSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @SneakyThrows
    @Override
    protected void configure(HttpSecurity http) {
        http
            // TODO disable CSRF because when enabled controllers aren't initialized
            //  and if they are, POST are getting 403
            .csrf().disable()

            .authorizeRequests()
            .anyRequest().authenticated()

            .and()
            .oauth2Client()

            .and()
            .logout()

            .and()
            .oauth2Login()
            .redirectionEndpoint().baseUri("/login/oauth2/code/cognito")
            .and()
        ;
    }
}
  • REST客户端认证(优先级1)
/**
 * Allow users to use a token (id-token, jwt) instead of the interactive login.
 * The token is specified as the "Authorization: Bearer ..." header.
 * </p>
 * To get a token, the cognito client-app needs to support USER_PASSWORD_AUTH then use the following command:
 * <pre>
 *     aws cognito-idp initiate-auth --auth-flow USER_PASSWORD_AUTH --output json \
 *         --region $region --client-id $clientid --auth-parameters "USERNAME=$username,PASSWORD=$password" \
 *         | jq .AuthenticationResult.IdToken
 * </pre>
 */
@Slf4j
@Configuration
@Profile({"cognito"})
@Order(1)
public class CognitoTokenBasedSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @SneakyThrows
    @Override
    protected void configure(HttpSecurity http) {
        http
            .requestMatcher(new RequestHeaderRequestMatcher("Authorization"))
            .authorizeRequests().anyRequest().authenticated()
            .and().oauth2ResourceServer().jwt()
        ;
    }

}

问题详情

升级SpringBoot依赖后,切换为使用SecurityFilterChain Bean,尝试的配置代码如下,持续抛出错误:Can't configure antMatchers after anyRequest

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        // TODO disable CSRF because when enabled controllers aren't initialized
        //  and if they are, POST are getting 403
        .csrf().disable()

        .authorizeRequests()
        .anyRequest().authenticated()

        .and()
        .oauth2Client()

        .and()
        .logout()

        .and()
        .oauth2Login()
        .redirectionEndpoint().baseUri("/login/oauth2/code/cognito")
        .and()

    http.authorizeRequests()
            .anyRequest().authenticated()
            .and().oauth2ResourceServer().jwt();

    return http.build();
}

解决方案

错误原因

你错误地将两个原本独立的WebSecurityConfigurerAdapter配置合并到了同一个SecurityFilterChain中,且重复调用.authorizeRequests()。Spring Security要求anyRequest().authenticated()必须是授权规则的最后一条,后续不能再添加任何匹配规则,这就是报错的核心原因。

另外,原配置通过@Order实现了请求的分流处理:优先级高的配置拦截带Authorization头的请求,优先级低的处理其他请求,升级后需要保留这种分流逻辑。

正确配置

创建两个独立的SecurityFilterChain Bean,分别对应原有的两种认证逻辑,并通过@Order指定优先级:

  1. REST客户端认证(优先级更高,先匹配请求)
@Bean
@Order(1)
public SecurityFilterChain tokenBasedSecurityFilterChain(HttpSecurity http) throws Exception {
    http
        .requestMatcher(new RequestHeaderRequestMatcher("Authorization"))
        .authorizeRequests(auth -> auth.anyRequest().authenticated())
        .oauth2ResourceServer(oauth2 -> oauth2.jwt());
    
    return http.build();
}
  1. 交互式/Web用户认证(优先级更低,处理剩余请求)
@Bean
@Order(2)
@EnableGlobalMethodSecurity(
    prePostEnabled = true,
    jsr250Enabled = true,
    securedEnabled = true
)
public SecurityFilterChain interactiveSecurityFilterChain(HttpSecurity http) throws Exception {
    http
        .csrf().disable() // 保留原CSRF禁用配置(建议后续排查问题,尽量启用CSRF保护)
        .authorizeRequests(auth -> auth.anyRequest().authenticated())
        .oauth2Client()
        .and()
        .logout()
        .and()
        .oauth2Login(oauth2 -> oauth2.redirectionEndpoint().baseUri("/login/oauth2/code/cognito"));
    
    return http.build();
}

关键说明

  • 两个SecurityFilterChain分别处理不同类型的请求:第一个拦截带Authorization头的请求做JWT认证,第二个处理所有其他请求走OAuth2交互式登录
  • 使用Lambda风格配置(.authorizeRequests(auth -> ...))简化代码,避免链式调用的逻辑错误
  • 通过@Order保证优先级,确保带Authorization头的请求先被匹配处理

内容的提问来源于stack exchange,提问作者Oscar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 23:30:26