commit
4e3517e03a
|
@ -221,6 +221,7 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||
if (configs == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
removeFromConfigurersAddedInInitializing(clazz);
|
||||
return new ArrayList<>(configs);
|
||||
}
|
||||
|
||||
|
@ -253,11 +254,16 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||
if (configs == null) {
|
||||
return null;
|
||||
}
|
||||
removeFromConfigurersAddedInInitializing(clazz);
|
||||
Assert.state(configs.size() == 1,
|
||||
() -> "Only one configurer expected for type " + clazz + ", but got " + configs);
|
||||
return (C) configs.get(0);
|
||||
}
|
||||
|
||||
private <C extends SecurityConfigurer<O, B>> void removeFromConfigurersAddedInInitializing(Class<C> clazz) {
|
||||
this.configurersAddedInInitializing.removeIf(clazz::isInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the {@link ObjectPostProcessor} to use.
|
||||
* @param objectPostProcessor the {@link ObjectPostProcessor} to use. Cannot be null
|
||||
|
|
|
@ -30,6 +30,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
|
@ -83,6 +84,24 @@ public class AbstractConfiguredSecurityBuilderTests {
|
|||
verify(DelegateSecurityConfigurer.CONFIGURER).configure(this.builder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildWhenConfigurerAppliesAndRemoveAnotherConfigurerThenNotConfigured() throws Exception {
|
||||
ApplyAndRemoveSecurityConfigurer.CONFIGURER = mock(SecurityConfigurer.class);
|
||||
this.builder.apply(new ApplyAndRemoveSecurityConfigurer());
|
||||
this.builder.build();
|
||||
verify(ApplyAndRemoveSecurityConfigurer.CONFIGURER, never()).init(this.builder);
|
||||
verify(ApplyAndRemoveSecurityConfigurer.CONFIGURER, never()).configure(this.builder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildWhenConfigurerAppliesAndRemoveAnotherConfigurersThenNotConfigured() throws Exception {
|
||||
ApplyAndRemoveAllSecurityConfigurer.CONFIGURER = mock(SecurityConfigurer.class);
|
||||
this.builder.apply(new ApplyAndRemoveAllSecurityConfigurer());
|
||||
this.builder.build();
|
||||
verify(ApplyAndRemoveAllSecurityConfigurer.CONFIGURER, never()).init(this.builder);
|
||||
verify(ApplyAndRemoveAllSecurityConfigurer.CONFIGURER, never()).configure(this.builder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConfigurerWhenMultipleConfigurersThenThrowIllegalStateException() throws Exception {
|
||||
TestConfiguredSecurityBuilder builder = new TestConfiguredSecurityBuilder(mock(ObjectPostProcessor.class),
|
||||
|
@ -130,6 +149,32 @@ public class AbstractConfiguredSecurityBuilderTests {
|
|||
assertThat(builder.getConfigurers(DelegateSecurityConfigurer.class)).hasSize(2);
|
||||
}
|
||||
|
||||
private static class ApplyAndRemoveSecurityConfigurer
|
||||
extends SecurityConfigurerAdapter<Object, TestConfiguredSecurityBuilder> {
|
||||
|
||||
private static SecurityConfigurer<Object, TestConfiguredSecurityBuilder> CONFIGURER;
|
||||
|
||||
@Override
|
||||
public void init(TestConfiguredSecurityBuilder builder) throws Exception {
|
||||
builder.apply(CONFIGURER);
|
||||
builder.removeConfigurer(CONFIGURER.getClass());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ApplyAndRemoveAllSecurityConfigurer
|
||||
extends SecurityConfigurerAdapter<Object, TestConfiguredSecurityBuilder> {
|
||||
|
||||
private static SecurityConfigurer<Object, TestConfiguredSecurityBuilder> CONFIGURER;
|
||||
|
||||
@Override
|
||||
public void init(TestConfiguredSecurityBuilder builder) throws Exception {
|
||||
builder.apply(CONFIGURER);
|
||||
builder.removeConfigurers(CONFIGURER.getClass());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DelegateSecurityConfigurer
|
||||
extends SecurityConfigurerAdapter<Object, TestConfiguredSecurityBuilder> {
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.concurrent.Callable;
|
|||
|
||||
import com.google.common.net.HttpHeaders;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -50,6 +51,7 @@ import org.springframework.security.config.annotation.SecurityContextChangedList
|
|||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.AnonymousConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
@ -61,6 +63,8 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
|||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.test.web.servlet.RequestCacheResultMatcher;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter;
|
||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
@ -336,6 +340,16 @@ public class HttpSecurityConfigurationTests {
|
|||
this.mockMvc.perform(get("/"));
|
||||
}
|
||||
|
||||
// gh-13203
|
||||
@Test
|
||||
public void disableConfigurerWhenAppliedByAnotherConfigurerThenNotApplied() {
|
||||
this.spring.register(ApplyCustomDslConfig.class).autowire();
|
||||
SecurityFilterChain filterChain = this.spring.getContext().getBean(SecurityFilterChain.class);
|
||||
List<Filter> filters = filterChain.getFilters();
|
||||
assertThat(filters).doesNotHaveAnyElementsOfTypes(DefaultLoginPageGeneratingFilter.class,
|
||||
DefaultLogoutPageGeneratingFilter.class);
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class NameController {
|
||||
|
||||
|
@ -575,6 +589,31 @@ public class HttpSecurityConfigurationTests {
|
|||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class ApplyCustomDslConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http.apply(CustomDsl.customDsl());
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class CustomDsl extends AbstractHttpConfigurer<CustomDsl, HttpSecurity> {
|
||||
|
||||
@Override
|
||||
public void init(HttpSecurity http) throws Exception {
|
||||
http.formLogin(FormLoginConfigurer::disable);
|
||||
}
|
||||
|
||||
static CustomDsl customDsl() {
|
||||
return new CustomDsl();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class DefaultConfigurer extends AbstractHttpConfigurer<DefaultConfigurer, HttpSecurity> {
|
||||
|
||||
boolean init;
|
||||
|
|
Loading…
Reference in New Issue