From 4493958f1328ba660a4d57fe01b23784c0686dc5 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Sat, 30 Sep 2023 09:04:04 +0100 Subject: [PATCH] Improve conditions for enabling WebFlux security This commit correct a mistake where AuthenticationManager was used instead of ReactiveAuthenticationManager. It also expands the conditions so that WebFlux security will be enabled when the user has defined their own SecurityWebFilterChain. In such a situation no other security-related beans may be needed to use WebFlux security as things may have been configured directly using the DSL. Closes gh-37504 --- .../ReactiveSecurityAutoConfiguration.java | 18 ++++++++++++------ ...ReactiveSecurityAutoConfigurationTests.java | 17 ++++++++++++++++- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfiguration.java index b4d4394bfe4a..5bcb151be46b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfiguration.java @@ -29,9 +29,10 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; -import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ReactiveAuthenticationManager; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.core.userdetails.ReactiveUserDetailsService; +import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.WebFilterChainProxy; import org.springframework.web.reactive.config.WebFluxConfigurer; @@ -54,20 +55,20 @@ public class ReactiveSecurityAutoConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnMissingBean(WebFilterChainProxy.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) - @Conditional(ReactiveAuthenticationManagerCondition.class) + @Conditional(EnableWebFluxSecurityCondition.class) @EnableWebFluxSecurity static class EnableWebFluxSecurityConfiguration { } - static final class ReactiveAuthenticationManagerCondition extends AnyNestedCondition { + static final class EnableWebFluxSecurityCondition extends AnyNestedCondition { - ReactiveAuthenticationManagerCondition() { + EnableWebFluxSecurityCondition() { super(ConfigurationPhase.REGISTER_BEAN); } - @ConditionalOnBean(AuthenticationManager.class) - static final class ConditionalOnAuthenticationManagerBean { + @ConditionalOnBean(ReactiveAuthenticationManager.class) + static final class ConditionalOnReactiveAuthenticationManagerBean { } @@ -76,6 +77,11 @@ static final class ConditionalOnReactiveUserDetailsService { } + @ConditionalOnBean(SecurityWebFilterChain.class) + static final class ConditionalOnSecurityWebFilterChain { + + } + } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfigurationTests.java index b046e89d970c..dd5dd07ef32d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfigurationTests.java @@ -25,9 +25,11 @@ import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.ReactiveAuthenticationManager; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; import org.springframework.security.core.userdetails.User; +import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.WebFilterChainProxy; import org.springframework.web.reactive.config.WebFluxConfigurer; @@ -57,11 +59,24 @@ void backsOffWhenReactiveAuthenticationManagerNotPresent() { } @Test - void enablesWebFluxSecurity() { + void enablesWebFluxSecurityWhenUserDetailsServiceIsPresent() { this.contextRunner.withUserConfiguration(UserDetailsServiceConfiguration.class) .run((context) -> assertThat(context).getBean(WebFilterChainProxy.class).isNotNull()); } + @Test + void enablesWebFluxSecurityWhenReactiveAuthenticationManagerIsPresent() { + this.contextRunner + .withBean(ReactiveAuthenticationManager.class, () -> mock(ReactiveAuthenticationManager.class)) + .run((context) -> assertThat(context).getBean(WebFilterChainProxy.class).isNotNull()); + } + + @Test + void enablesWebFluxSecurityWhenSecurityWebFilterChainIsPresent() { + this.contextRunner.withBean(SecurityWebFilterChain.class, () -> mock(SecurityWebFilterChain.class)) + .run((context) -> assertThat(context).getBean(WebFilterChainProxy.class).isNotNull()); + } + @Test void autoConfigurationIsConditionalOnClass() { this.contextRunner