Skip to content

Commit b47420f

Browse files
Merge branch '5.7.x' into 5.8.x
Closes gh-13280
2 parents 9ac286e + 7250abc commit b47420f

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;
@@ -46,6 +47,7 @@
4647
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
4748
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
4849
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
50+
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
4951
import org.springframework.security.config.test.SpringTestContext;
5052
import org.springframework.security.config.test.SpringTestContextExtension;
5153
import org.springframework.security.core.Authentication;
@@ -56,6 +58,8 @@
5658
import org.springframework.security.core.userdetails.UserDetailsService;
5759
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
5860
import org.springframework.security.web.SecurityFilterChain;
61+
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
62+
import org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter;
5963
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
6064
import org.springframework.test.web.servlet.MockMvc;
6165
import org.springframework.test.web.servlet.MvcResult;
@@ -323,6 +327,16 @@ public void getWhenCustomContentNegotiationStrategyThenUses() throws Exception {
323327
.resolveMediaTypes(any(NativeWebRequest.class));
324328
}
325329

330+
// gh-13203
331+
@Test
332+
public void disableConfigurerWhenAppliedByAnotherConfigurerThenNotApplied() {
333+
this.spring.register(ApplyCustomDslConfig.class).autowire();
334+
SecurityFilterChain filterChain = this.spring.getContext().getBean(SecurityFilterChain.class);
335+
List<Filter> filters = filterChain.getFilters();
336+
assertThat(filters).doesNotHaveAnyElementsOfTypes(DefaultLoginPageGeneratingFilter.class,
337+
DefaultLogoutPageGeneratingFilter.class);
338+
}
339+
326340
@RestController
327341
static class NameController {
328342

@@ -525,6 +539,31 @@ static ContentNegotiationStrategy cns() {
525539

526540
}
527541

542+
@Configuration
543+
@EnableWebSecurity
544+
static class ApplyCustomDslConfig {
545+
546+
@Bean
547+
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
548+
http.apply(CustomDsl.customDsl());
549+
return http.build();
550+
}
551+
552+
}
553+
554+
static class CustomDsl extends AbstractHttpConfigurer<CustomDsl, HttpSecurity> {
555+
556+
@Override
557+
public void init(HttpSecurity http) throws Exception {
558+
http.formLogin(FormLoginConfigurer::disable);
559+
}
560+
561+
static CustomDsl customDsl() {
562+
return new CustomDsl();
563+
}
564+
565+
}
566+
528567
static class DefaultConfigurer extends AbstractHttpConfigurer<DefaultConfigurer, HttpSecurity> {
529568

530569
boolean init;

0 commit comments

Comments
 (0)