Skip to content

Commit 7250abc

Browse files
Does not apply a Configurer when disabled from another DSL
Closes gh-13203
1 parent 06e58e4 commit 7250abc

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ public <C extends SecurityConfigurer<O, B>> List<C> removeConfigurers(Class<C> c
221221
if (configs == null) {
222222
return new ArrayList<>();
223223
}
224+
removeFromConfigurersAddedInInitializing(clazz);
224225
return new ArrayList<>(configs);
225226
}
226227

@@ -253,11 +254,16 @@ public <C extends SecurityConfigurer<O, B>> C removeConfigurer(Class<C> clazz) {
253254
if (configs == null) {
254255
return null;
255256
}
257+
removeFromConfigurersAddedInInitializing(clazz);
256258
Assert.state(configs.size() == 1,
257259
() -> "Only one configurer expected for type " + clazz + ", but got " + configs);
258260
return (C) configs.get(0);
259261
}
260262

263+
private <C extends SecurityConfigurer<O, B>> void removeFromConfigurersAddedInInitializing(Class<C> clazz) {
264+
this.configurersAddedInInitializing.removeIf(clazz::isInstance);
265+
}
266+
261267
/**
262268
* Specifies the {@link ObjectPostProcessor} to use.
263269
* @param objectPostProcessor the {@link ObjectPostProcessor} to use. Cannot be null

config/src/test/java/org/springframework/security/config/annotation/web/AbstractConfiguredSecurityBuilderTests.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
3131
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
3232
import static org.mockito.Mockito.mock;
33+
import static org.mockito.Mockito.never;
3334
import static org.mockito.Mockito.verify;
3435

3536
/**
@@ -83,6 +84,24 @@ public void buildWhenConfigurerAppliesAnotherConfigurerThenObjectStillBuilds() t
8384
verify(DelegateSecurityConfigurer.CONFIGURER).configure(this.builder);
8485
}
8586

87+
@Test
88+
public void buildWhenConfigurerAppliesAndRemoveAnotherConfigurerThenNotConfigured() throws Exception {
89+
ApplyAndRemoveSecurityConfigurer.CONFIGURER = mock(SecurityConfigurer.class);
90+
this.builder.apply(new ApplyAndRemoveSecurityConfigurer());
91+
this.builder.build();
92+
verify(ApplyAndRemoveSecurityConfigurer.CONFIGURER, never()).init(this.builder);
93+
verify(ApplyAndRemoveSecurityConfigurer.CONFIGURER, never()).configure(this.builder);
94+
}
95+
96+
@Test
97+
public void buildWhenConfigurerAppliesAndRemoveAnotherConfigurersThenNotConfigured() throws Exception {
98+
ApplyAndRemoveAllSecurityConfigurer.CONFIGURER = mock(SecurityConfigurer.class);
99+
this.builder.apply(new ApplyAndRemoveAllSecurityConfigurer());
100+
this.builder.build();
101+
verify(ApplyAndRemoveAllSecurityConfigurer.CONFIGURER, never()).init(this.builder);
102+
verify(ApplyAndRemoveAllSecurityConfigurer.CONFIGURER, never()).configure(this.builder);
103+
}
104+
86105
@Test
87106
public void getConfigurerWhenMultipleConfigurersThenThrowIllegalStateException() throws Exception {
88107
TestConfiguredSecurityBuilder builder = new TestConfiguredSecurityBuilder(mock(ObjectPostProcessor.class),
@@ -130,6 +149,32 @@ public void getConfigurersWhenMultipleConfigurersThenConfigurersReturned() throw
130149
assertThat(builder.getConfigurers(DelegateSecurityConfigurer.class)).hasSize(2);
131150
}
132151

152+
private static class ApplyAndRemoveSecurityConfigurer
153+
extends SecurityConfigurerAdapter<Object, TestConfiguredSecurityBuilder> {
154+
155+
private static SecurityConfigurer<Object, TestConfiguredSecurityBuilder> CONFIGURER;
156+
157+
@Override
158+
public void init(TestConfiguredSecurityBuilder builder) throws Exception {
159+
builder.apply(CONFIGURER);
160+
builder.removeConfigurer(CONFIGURER.getClass());
161+
}
162+
163+
}
164+
165+
private static class ApplyAndRemoveAllSecurityConfigurer
166+
extends SecurityConfigurerAdapter<Object, TestConfiguredSecurityBuilder> {
167+
168+
private static SecurityConfigurer<Object, TestConfiguredSecurityBuilder> CONFIGURER;
169+
170+
@Override
171+
public void init(TestConfiguredSecurityBuilder builder) throws Exception {
172+
builder.apply(CONFIGURER);
173+
builder.removeConfigurers(CONFIGURER.getClass());
174+
}
175+
176+
}
177+
133178
private static class DelegateSecurityConfigurer
134179
extends SecurityConfigurerAdapter<Object, TestConfiguredSecurityBuilder> {
135180

config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.List;
2222
import java.util.concurrent.Callable;
2323

24+
import javax.servlet.Filter;
2425
import javax.servlet.http.HttpServletRequest;
2526

2627
import com.google.common.net.HttpHeaders;
@@ -45,6 +46,7 @@
4546
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
4647
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
4748
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
49+
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
4850
import org.springframework.security.config.test.SpringTestContext;
4951
import org.springframework.security.config.test.SpringTestContextExtension;
5052
import org.springframework.security.core.Authentication;
@@ -55,6 +57,8 @@
5557
import org.springframework.security.core.userdetails.UserDetailsService;
5658
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
5759
import org.springframework.security.web.SecurityFilterChain;
60+
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
61+
import org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter;
5862
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
5963
import org.springframework.test.web.servlet.MockMvc;
6064
import org.springframework.test.web.servlet.MvcResult;
@@ -292,6 +296,16 @@ public void configureWhenDefaultConfigurerAsSpringFactoryThenDefaultConfigurerAp
292296
assertThat(configurer.configure).isTrue();
293297
}
294298

299+
// gh-13203
300+
@Test
301+
public void disableConfigurerWhenAppliedByAnotherConfigurerThenNotApplied() {
302+
this.spring.register(ApplyCustomDslConfig.class).autowire();
303+
SecurityFilterChain filterChain = this.spring.getContext().getBean(SecurityFilterChain.class);
304+
List<Filter> filters = filterChain.getFilters();
305+
assertThat(filters).doesNotHaveAnyElementsOfTypes(DefaultLoginPageGeneratingFilter.class,
306+
DefaultLogoutPageGeneratingFilter.class);
307+
}
308+
295309
@RestController
296310
static class NameController {
297311

@@ -470,6 +484,31 @@ void user(HttpServletRequest request) {
470484

471485
}
472486

487+
@Configuration
488+
@EnableWebSecurity
489+
static class ApplyCustomDslConfig {
490+
491+
@Bean
492+
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
493+
http.apply(CustomDsl.customDsl());
494+
return http.build();
495+
}
496+
497+
}
498+
499+
static class CustomDsl extends AbstractHttpConfigurer<CustomDsl, HttpSecurity> {
500+
501+
@Override
502+
public void init(HttpSecurity http) throws Exception {
503+
http.formLogin(FormLoginConfigurer::disable);
504+
}
505+
506+
static CustomDsl customDsl() {
507+
return new CustomDsl();
508+
}
509+
510+
}
511+
473512
static class DefaultConfigurer extends AbstractHttpConfigurer<DefaultConfigurer, HttpSecurity> {
474513

475514
boolean init;

0 commit comments

Comments
 (0)