Make reactive security back off without authentication manager
If there's no authentication manager bean or no bean from which one can be created, Spring Security's reactive support may fail to bootstrap due to a null authentication manager. This commit causes the auto-configuration that enables WebFlux security to back off in the absence of an AuthenticationManager bean and a ReactiveUserDetailsService (from which Spring Security can create an AuthenticationManager) bean. Other reactive security auto-configuration that can configure things such that WebFlux security can be bootstrapped without an AuthenticationManager has been updated to enable WebFlux security rather than relying on another auto-configuration class to do so. Fixes gh-37504
This commit is contained in:
parent
1d60e42a73
commit
ee9c74556d
|
@ -35,6 +35,7 @@ import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2Res
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity.OAuth2ResourceServerSpec;
|
||||
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
|
||||
|
@ -49,6 +50,7 @@ import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder.JwkSetUr
|
|||
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
|
||||
import org.springframework.security.oauth2.jwt.SupplierReactiveJwtDecoder;
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
||||
import org.springframework.security.web.server.WebFilterChainProxy;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
|
@ -177,6 +179,13 @@ class ReactiveOAuth2ResourceServerJwkConfiguration {
|
|||
server.jwt((jwt) -> jwt.jwtDecoder(decoder));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingBean(WebFilterChainProxy.class)
|
||||
@EnableWebFluxSecurity
|
||||
static class EnableWebFluxSecurityConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,10 +22,12 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|||
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.SpringReactiveOpaqueTokenIntrospector;
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
||||
import org.springframework.security.web.server.WebFilterChainProxy;
|
||||
|
||||
import static org.springframework.security.config.Customizer.withDefaults;
|
||||
|
||||
|
@ -64,6 +66,13 @@ class ReactiveOAuth2ResourceServerOpaqueTokenConfiguration {
|
|||
return http.build();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingBean(WebFilterChainProxy.class)
|
||||
@EnableWebFluxSecurity
|
||||
static class EnableWebFluxSecurityConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
|
@ -20,13 +20,18 @@ import reactor.core.publisher.Flux;
|
|||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
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.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
|
||||
import org.springframework.security.web.server.WebFilterChainProxy;
|
||||
import org.springframework.web.reactive.config.WebFluxConfigurer;
|
||||
|
||||
|
@ -49,9 +54,28 @@ public class ReactiveSecurityAutoConfiguration {
|
|||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnMissingBean(WebFilterChainProxy.class)
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
|
||||
@Conditional(ReactiveAuthenticationManagerCondition.class)
|
||||
@EnableWebFluxSecurity
|
||||
static class EnableWebFluxSecurityConfiguration {
|
||||
|
||||
}
|
||||
|
||||
static final class ReactiveAuthenticationManagerCondition extends AnyNestedCondition {
|
||||
|
||||
ReactiveAuthenticationManagerCondition() {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ConditionalOnBean(AuthenticationManager.class)
|
||||
static final class ConditionalOnAuthenticationManagerBean {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnBean(ReactiveUserDetailsService.class)
|
||||
static final class ConditionalOnReactiveUserDetailsService {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
|
@ -55,7 +55,7 @@ import org.springframework.util.StringUtils;
|
|||
* @author Madhura Bhave
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@AutoConfiguration(after = RSocketMessagingAutoConfiguration.class)
|
||||
@AutoConfiguration(before = ReactiveSecurityAutoConfiguration.class, after = RSocketMessagingAutoConfiguration.class)
|
||||
@ConditionalOnClass({ ReactiveAuthenticationManager.class })
|
||||
@ConditionalOnMissingBean(
|
||||
value = { ReactiveAuthenticationManager.class, ReactiveUserDetailsService.class,
|
||||
|
|
|
@ -740,7 +740,6 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests {
|
|||
.isEqualTo("aud");
|
||||
}
|
||||
|
||||
@EnableWebFluxSecurity
|
||||
static class TestConfig {
|
||||
|
||||
@Bean
|
||||
|
@ -782,6 +781,7 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests {
|
|||
|
||||
}
|
||||
|
||||
@EnableWebFluxSecurity
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class SecurityWebFilterChainConfig {
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.junit.jupiter.api.Test;
|
|||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration.EnableWebFluxSecurityConfiguration;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -47,6 +48,13 @@ class ReactiveSecurityAutoConfigurationTests {
|
|||
.run((context) -> assertThat(context).hasSingleBean(WebFilterChainProxy.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void backsOffWhenReactiveAuthenticationManagerNotPresent() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class))
|
||||
.run((context) -> assertThat(context).hasSingleBean(ReactiveSecurityAutoConfiguration.class)
|
||||
.doesNotHaveBean(EnableWebFluxSecurityConfiguration.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void enablesWebFluxSecurity() {
|
||||
this.contextRunner
|
||||
|
|
Loading…
Reference in New Issue