commit
907e4d97f7
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure.security.reactive;
|
package org.springframework.boot.actuate.autoconfigure.security.reactive;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration;
|
||||||
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
|
||||||
import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
|
||||||
|
@ -28,10 +30,14 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
|
||||||
import org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration;
|
import org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration;
|
import org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration;
|
import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
||||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||||
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
|
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
|
||||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||||
|
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
import org.springframework.security.web.server.SecurityWebFilterChain;
|
||||||
import org.springframework.security.web.server.WebFilterChainProxy;
|
import org.springframework.security.web.server.WebFilterChainProxy;
|
||||||
import org.springframework.web.cors.reactive.PreFlightRequestHandler;
|
import org.springframework.web.cors.reactive.PreFlightRequestHandler;
|
||||||
|
@ -50,7 +56,8 @@ import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
@AutoConfiguration(before = ReactiveSecurityAutoConfiguration.class,
|
@AutoConfiguration(before = ReactiveSecurityAutoConfiguration.class,
|
||||||
after = { HealthEndpointAutoConfiguration.class, InfoEndpointAutoConfiguration.class,
|
after = { HealthEndpointAutoConfiguration.class, InfoEndpointAutoConfiguration.class,
|
||||||
WebEndpointAutoConfiguration.class, ReactiveOAuth2ClientAutoConfiguration.class,
|
WebEndpointAutoConfiguration.class, ReactiveOAuth2ClientAutoConfiguration.class,
|
||||||
ReactiveOAuth2ResourceServerAutoConfiguration.class })
|
ReactiveOAuth2ResourceServerAutoConfiguration.class,
|
||||||
|
ReactiveUserDetailsServiceAutoConfiguration.class })
|
||||||
@ConditionalOnClass({ EnableWebFluxSecurity.class, WebFilterChainProxy.class })
|
@ConditionalOnClass({ EnableWebFluxSecurity.class, WebFilterChainProxy.class })
|
||||||
@ConditionalOnMissingBean({ SecurityWebFilterChain.class, WebFilterChainProxy.class })
|
@ConditionalOnMissingBean({ SecurityWebFilterChain.class, WebFilterChainProxy.class })
|
||||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
|
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
|
||||||
|
@ -69,4 +76,10 @@ public class ReactiveManagementWebSecurityAutoConfiguration {
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean({ ReactiveAuthenticationManager.class, ReactiveUserDetailsService.class })
|
||||||
|
ReactiveAuthenticationManager denyAllAuthenticationManager() {
|
||||||
|
return (authentication) -> Mono.error(new UsernameNotFoundException(authentication.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -71,17 +71,26 @@ class ReactiveManagementWebSecurityAutoConfigurationTests {
|
||||||
HealthEndpointAutoConfiguration.class, InfoEndpointAutoConfiguration.class,
|
HealthEndpointAutoConfiguration.class, InfoEndpointAutoConfiguration.class,
|
||||||
WebFluxAutoConfiguration.class, EnvironmentEndpointAutoConfiguration.class,
|
WebFluxAutoConfiguration.class, EnvironmentEndpointAutoConfiguration.class,
|
||||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||||
ReactiveSecurityAutoConfiguration.class, ReactiveManagementWebSecurityAutoConfiguration.class))
|
ReactiveSecurityAutoConfiguration.class, ReactiveManagementWebSecurityAutoConfiguration.class));
|
||||||
.withUserConfiguration(UserDetailsServiceConfiguration.class);
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void permitAllForHealth() {
|
void permitAllForHealth() {
|
||||||
this.contextRunner.run((context) -> assertThat(getAuthenticateHeader(context, "/actuator/health")).isNull());
|
this.contextRunner.withUserConfiguration(UserDetailsServiceConfiguration.class)
|
||||||
|
.run((context) -> assertThat(getAuthenticateHeader(context, "/actuator/health")).isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void securesEverythingElse() {
|
void securesEverythingElse() {
|
||||||
|
this.contextRunner.withUserConfiguration(UserDetailsServiceConfiguration.class).run((context) -> {
|
||||||
|
assertThat(getAuthenticateHeader(context, "/actuator").get(0)).contains("Basic realm=");
|
||||||
|
assertThat(getAuthenticateHeader(context, "/foo").toString()).contains("Basic realm=");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void noExistingAuthenticationManagerOrUserDetailsService() {
|
||||||
this.contextRunner.run((context) -> {
|
this.contextRunner.run((context) -> {
|
||||||
|
assertThat(getAuthenticateHeader(context, "/actuator/health")).isNull();
|
||||||
assertThat(getAuthenticateHeader(context, "/actuator").get(0)).contains("Basic realm=");
|
assertThat(getAuthenticateHeader(context, "/actuator").get(0)).contains("Basic realm=");
|
||||||
assertThat(getAuthenticateHeader(context, "/foo").toString()).contains("Basic realm=");
|
assertThat(getAuthenticateHeader(context, "/foo").toString()).contains("Basic realm=");
|
||||||
});
|
});
|
||||||
|
@ -89,10 +98,12 @@ class ReactiveManagementWebSecurityAutoConfigurationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void usesMatchersBasedOffConfiguredActuatorBasePath() {
|
void usesMatchersBasedOffConfiguredActuatorBasePath() {
|
||||||
this.contextRunner.withPropertyValues("management.endpoints.web.base-path=/").run((context) -> {
|
this.contextRunner.withUserConfiguration(UserDetailsServiceConfiguration.class)
|
||||||
assertThat(getAuthenticateHeader(context, "/health")).isNull();
|
.withPropertyValues("management.endpoints.web.base-path=/")
|
||||||
assertThat(getAuthenticateHeader(context, "/foo").get(0)).contains("Basic realm=");
|
.run((context) -> {
|
||||||
});
|
assertThat(getAuthenticateHeader(context, "/health")).isNull();
|
||||||
|
assertThat(getAuthenticateHeader(context, "/foo").get(0)).contains("Basic realm=");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -180,6 +191,11 @@ class ReactiveManagementWebSecurityAutoConfigurationTests {
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
ReactiveAuthenticationManager authenticationManager() {
|
||||||
|
return mock(ReactiveAuthenticationManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
|
Loading…
Reference in New Issue