From 9f9fbb395f5818e95307b231188ff39945e8e5b1 Mon Sep 17 00:00:00 2001 From: Eleftheria Stein Date: Tue, 8 Feb 2022 12:14:49 +0100 Subject: [PATCH] Apply configurers from spring.factories to HttpSecurity bean Closes gh-10814 --- .../HttpSecurityConfiguration.java | 15 ++++++- .../HttpSecurityConfigurationTests.java | 42 ++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java index 2aad5f658a..468ba74bf5 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package org.springframework.security.config.annotation.web.configuration; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; @@ -24,11 +25,13 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; +import org.springframework.core.io.support.SpringFactoriesLoader; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; 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.DefaultLoginPageConfigurer; import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter; @@ -97,6 +100,7 @@ class HttpSecurityConfiguration { .apply(new DefaultLoginPageConfigurer<>()); http.logout(withDefaults()); // @formatter:on + applyDefaultConfigurers(http); return http; } @@ -105,6 +109,15 @@ class HttpSecurityConfiguration { : this.authenticationConfiguration.getAuthenticationManager(); } + private void applyDefaultConfigurers(HttpSecurity http) throws Exception { + ClassLoader classLoader = this.context.getClassLoader(); + List defaultHttpConfigurers = SpringFactoriesLoader + .loadFactories(AbstractHttpConfigurer.class, classLoader); + for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) { + http.apply(configurer); + } + } + private Map, Object> createSharedObjects() { Map, Object> sharedObjects = new HashMap<>(); sharedObjects.put(ApplicationContext.class, this.context); diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java index d6d00d7f4c..5c4f3ebbd6 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.security.config.annotation.web.configuration; +import java.util.Arrays; import java.util.concurrent.Callable; import jakarta.servlet.http.HttpServletRequest; @@ -23,15 +24,20 @@ import jakarta.servlet.http.HttpServletRequest; import com.google.common.net.HttpHeaders; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.support.SpringFactoriesLoader; import org.springframework.mock.web.MockHttpSession; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.test.SpringTestContext; import org.springframework.security.config.test.SpringTestContextExtension; import org.springframework.security.core.context.SecurityContextHolder; @@ -67,7 +73,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * * @author Eleftheria Stein */ -@ExtendWith(SpringTestContextExtension.class) +@ExtendWith({ MockitoExtension.class, SpringTestContextExtension.class }) public class HttpSecurityConfigurationTests { public final SpringTestContext spring = new SpringTestContext(this); @@ -75,6 +81,9 @@ public class HttpSecurityConfigurationTests { @Autowired private MockMvc mockMvc; + @Mock + private MockedStatic springFactoriesLoader; + @Test public void postWhenDefaultFilterChainBeanThenRespondsWithForbidden() throws Exception { this.spring.register(DefaultWithFilterChainConfig.class).autowire(); @@ -220,6 +229,17 @@ public class HttpSecurityConfigurationTests { "authorizeHttpRequests cannot be used in conjunction with authorizeRequests. Please select just one."); } + @Test + public void configureWhenDefaultConfigurerAsSpringFactoryThenDefaultConfigurerApplied() { + DefaultConfigurer configurer = new DefaultConfigurer(); + this.springFactoriesLoader.when( + () -> SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, getClass().getClassLoader())) + .thenReturn(Arrays.asList(configurer)); + this.spring.register(DefaultWithFilterChainConfig.class).autowire(); + assertThat(configurer.init).isTrue(); + assertThat(configurer.configure).isTrue(); + } + @RestController static class NameController { @@ -349,4 +369,22 @@ public class HttpSecurityConfigurationTests { } + static class DefaultConfigurer extends AbstractHttpConfigurer { + + boolean init; + + boolean configure; + + @Override + public void init(HttpSecurity builder) { + this.init = true; + } + + @Override + public void configure(HttpSecurity builder) { + this.configure = true; + } + + } + }