commit
a939fa63a1
|
@ -221,6 +221,7 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
||||||
if (configs == null) {
|
if (configs == null) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
removeFromConfigurersAddedInInitializing(clazz);
|
||||||
return new ArrayList<>(configs);
|
return new ArrayList<>(configs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,11 +254,16 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
||||||
if (configs == null) {
|
if (configs == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
removeFromConfigurersAddedInInitializing(clazz);
|
||||||
Assert.state(configs.size() == 1,
|
Assert.state(configs.size() == 1,
|
||||||
() -> "Only one configurer expected for type " + clazz + ", but got " + configs);
|
() -> "Only one configurer expected for type " + clazz + ", but got " + configs);
|
||||||
return (C) configs.get(0);
|
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.
|
* Specifies the {@link ObjectPostProcessor} to use.
|
||||||
* @param objectPostProcessor the {@link ObjectPostProcessor} to use. Cannot be null
|
* @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.assertThatIllegalArgumentException;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,6 +84,24 @@ public class AbstractConfiguredSecurityBuilderTests {
|
||||||
verify(DelegateSecurityConfigurer.CONFIGURER).configure(this.builder);
|
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
|
@Test
|
||||||
public void getConfigurerWhenMultipleConfigurersThenThrowIllegalStateException() throws Exception {
|
public void getConfigurerWhenMultipleConfigurersThenThrowIllegalStateException() throws Exception {
|
||||||
TestConfiguredSecurityBuilder builder = new TestConfiguredSecurityBuilder(mock(ObjectPostProcessor.class),
|
TestConfiguredSecurityBuilder builder = new TestConfiguredSecurityBuilder(mock(ObjectPostProcessor.class),
|
||||||
|
@ -130,6 +149,32 @@ public class AbstractConfiguredSecurityBuilderTests {
|
||||||
assertThat(builder.getConfigurers(DelegateSecurityConfigurer.class)).hasSize(2);
|
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
|
private static class DelegateSecurityConfigurer
|
||||||
extends SecurityConfigurerAdapter<Object, TestConfiguredSecurityBuilder> {
|
extends SecurityConfigurerAdapter<Object, TestConfiguredSecurityBuilder> {
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import com.google.common.net.HttpHeaders;
|
import com.google.common.net.HttpHeaders;
|
||||||
import io.micrometer.observation.ObservationRegistry;
|
import io.micrometer.observation.ObservationRegistry;
|
||||||
|
import jakarta.servlet.Filter;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.junit.jupiter.api.Test;
|
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.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
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.AnonymousConfigurer;
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
|
||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.core.Authentication;
|
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.provisioning.InMemoryUserDetailsManager;
|
||||||
import org.springframework.security.test.web.servlet.RequestCacheResultMatcher;
|
import org.springframework.security.test.web.servlet.RequestCacheResultMatcher;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
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.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
|
@ -336,6 +340,16 @@ public class HttpSecurityConfigurationTests {
|
||||||
this.mockMvc.perform(get("/"));
|
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
|
@RestController
|
||||||
static class NameController {
|
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> {
|
static class DefaultConfigurer extends AbstractHttpConfigurer<DefaultConfigurer, HttpSecurity> {
|
||||||
|
|
||||||
boolean init;
|
boolean init;
|
||||||
|
|
Loading…
Reference in New Issue