弃用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指定优先级:
- 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(); }
- 交互式/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
相关产品推荐
相关产品推荐

