Describe the bug
After upgrading from Spring Boot 3.3.X to 3.4.0, thus using Spring Security 6.4.0 we encountered the problem, that we think that the evaluation of anyRequestFilterChain is not handled correctly. We have 2 filter chains, the first one was correctly identified as anyRequestFilterChain, while the second one is matching on /login. The problem we think is, that the evaluation happens too early, it should happen in Line 316 and not in 308 as seen in the screenshot. Do you agree with that, or did we understand something wrong?
To Reproduce
Add two filterChains, one with anyRequest and one with e.g. /login as seen in the code example below.
Expected behavior
We believe this configuration should not result in the error, that there are more than one filter chain that matches any request.
Sample
Add these two Beans to a Configuration:
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf(AbstractHttpConfigurer::disable);
return httpSecurity.build();
}
@Bean
public SecurityFilterChain defaultLoginFormFilterChain(HttpSecurity http) throws Exception {
return http.securityMatcher("/login")
.authorizeHttpRequests(authorize -> authorize.anyRequest()
.permitAll())
.formLogin(formLogin -> formLogin.defaultSuccessUrl("/swagger-ui/index.html"))
.build();
}
Reports that include a sample will take priority over reports that do not. At times, we may require a sample, so it is good to try and include a sample up front.
Comment From: franticticktick
Hi @coinzz, could you please pay attention to this? It seems this is your case.
Comment From: coinzz
Ahh thank you, I will take a look with a colleague on that later as well. I'm still a bit new to the Security configurations, but as far as I understand this now: this is absolutely correct in your implementation, because it shows that my securityFilterChain currently has some issues, because it defines an anyRequest filter at first and something else after that, which in fact has no impact anymore, because the first filter on anyRequest wins in all cases, am I right?
Comment From: franticticktick
@coinzz you are right, in fact, in your configuration only one filterChain is relevant, the second filterChain becomes useless.
Comment From: coinzz
Yeah, using this
@Bean
@Order(Ordered.LOWEST_PRECEDENCE)
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf(AbstractHttpConfigurer::disable);
return httpSecurity.build();
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain defaultLoginFormFilterChain(HttpSecurity http) throws Exception {
return http.securityMatcher("/login")
.authorizeHttpRequests(authorize -> authorize.anyRequest()
.permitAll())
.formLogin(formLogin -> formLogin.defaultSuccessUrl("/swagger-ui/index.html"))
.build();
}
it works. Thank you for clarification that the anyRequest should always be the last filter 😊
Maybe you can edit the error message a little bit, since it suggested that we already have an anyRequestFilterChain, but actually the problem is that all filter chains after the anyRequestFilterChain will be ignored and this is probably unwanted. But nice work in blocking this probably unwanted configuration.
Comment From: sjohnr
Maybe you can edit the error message a little bit, since it suggested that we already have an
anyRequestFilterChain, but actually the problem is that all filter chains after theanyRequestFilterChainwill be ignored and this is probably unwanted.
Just a note, @coinzz that the information you're requesting is in fact already in the error message at the end (emphasis added):
A filter chain that matches any request [...] has already been configured, which means that this filter chain [...] will never get invoked. Please use
HttpSecurity#securityMatcherto ensure that there is only one filter chain configured for 'any request' and that the 'any request' filter chain is published last.
Comment From: coinzz
Sorry my bad, thank's a lot 😊