I'm using
- Spring Boot 2.7.12
- Spring Security 5.8.3
(I did test with Spring Boot 3.1.0, and I am facing the same issue)
Describe the bug
While playing around with Custom DSL, I noticed 2 additional filters are being applied when using custom dsl.
- DefaultLoginPageGeneratingFilter
- DefaultLogoutPageGeneratingFilter
Not exactly sure if this is intended behavior, but I thought it shouldn't be?
To Reproduce Here's the following code
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity(debug = true)
public class WebSecurityConfig {
@Bean
public SecurityFilterChain docsFilterChain(HttpSecurity http) throws Exception {
return http
// .apply(DummyDsl.dummyDsl())
// .and()
.build();
}
}
public class DummyDsl extends AbstractHttpConfigurer<DummyDsl, HttpSecurity> {
@Override
public void init(HttpSecurity http) throws Exception {
http.formLogin(AbstractHttpConfigurer::disable);
}
public static DummyDsl dummyDsl() {
return new DummyDsl();
}
}
When custom dsl is not applied, this is the filter chain
Security filter chain: [
DisableEncodeUrlFilter
WebAsyncManagerIntegrationFilter
SecurityContextHolderFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
ExceptionTranslationFilter
]
But when it is being applied, this is the filter chain
Security filter chain: [
DisableEncodeUrlFilter
WebAsyncManagerIntegrationFilter
SecurityContextHolderFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
ExceptionTranslationFilter
]
Expected behavior I should expect that the filter chain should be same across both setup, unless I am missing something (I hope not)?
Sample You can find the reproduce over at spring-security-custom-dsl-bug
Additional Notes
As the docs isn't very explicit, but can I assume that the custom dsl is used for, or at least, can be used for the purpose of having a common configuration that can be re-use in different SecurityFilterChain?
Comment From: marcusdacoregio
Hi @bwgjoseph, thanks for the report.
That is not the expected behavior, since you disabled formLogin() there should be no DefaultLoginPageGeneratingFilter in place. The problem is that the builder's init() method invokes your custom DSL and the DSL adds the FormLoginConfigurer to the configurers list. Since the buildState is INITIALIZING, it also adds the FormLoginConfigurer to the configurersAddedInInitializing list, see https://github.com/spring-projects/spring-security/blob/9ec3e80e15c709502633447beeef36f957e2c4e4/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java#L191C32-L193.
When you invoke disable(), the AbstractConfiguredSecurityBuilder#removeConfigurer is invoked removing that configurer from the configurers list, but not removed from the configurersAddedInInitializing list.
And then, the FormLoginConfigurer is initialized here https://github.com/spring-projects/spring-security/blob/9ec3e80e15c709502633447beeef36f957e2c4e4/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java#L341, setting the DefaultLoginPageGeneratingFilter#formLoginEnabled to true.
I believe that when a configurer is removed, it should be removed from both lists. That said, I opened https://github.com/spring-projects/spring-security/pull/13235 to fix that.
Comment From: bwgjoseph
Thanks for the fix and explanation!
With what you have explained, I imagine that this should fix for anything that I configure (to disable) from customdsl.init() as well.
Also, in case you missed it, can I use custom-dsl as a way to provide as common configuration among/across different SecurityFilterChain?
Comment From: marcusdacoregio
Also, in case you missed it, can I use custom-dsl as a way to provide as common configuration among/across different SecurityFilterChain?
Yes, you can. You can also make the Custom DSL to be picked up by HttpSecurity by adding it to the spring.factories file.