mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Make user details only back off without custom username or password
Closes gh-38864
This commit is contained in:
parent
0f53415451
commit
961da4e428
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -29,6 +29,7 @@ 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.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
@ -58,13 +59,12 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
@AutoConfiguration(before = ReactiveSecurityAutoConfiguration.class, after = RSocketMessagingAutoConfiguration.class)
|
||||
@ConditionalOnClass({ ReactiveAuthenticationManager.class })
|
||||
@ConditionalOnMissingClass({ "org.springframework.security.oauth2.client.registration.ClientRegistrationRepository",
|
||||
"org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector" })
|
||||
@ConditionalOnMissingBean(
|
||||
value = { ReactiveAuthenticationManager.class, ReactiveUserDetailsService.class,
|
||||
ReactiveAuthenticationManagerResolver.class },
|
||||
type = { "org.springframework.security.oauth2.jwt.ReactiveJwtDecoder" })
|
||||
@Conditional(ReactiveUserDetailsServiceAutoConfiguration.ReactiveUserDetailsServiceCondition.class)
|
||||
@Conditional({ ReactiveUserDetailsServiceAutoConfiguration.RSocketEnabledOrReactiveWebApplication.class,
|
||||
ReactiveUserDetailsServiceAutoConfiguration.MissingAlternativeOrUserPropertiesConfigured.class })
|
||||
@EnableConfigurationProperties(SecurityProperties.class)
|
||||
public class ReactiveUserDetailsServiceAutoConfiguration {
|
||||
|
||||
@ -98,9 +98,9 @@ public class ReactiveUserDetailsServiceAutoConfiguration {
|
||||
return NOOP_PASSWORD_PREFIX + password;
|
||||
}
|
||||
|
||||
static class ReactiveUserDetailsServiceCondition extends AnyNestedCondition {
|
||||
static class RSocketEnabledOrReactiveWebApplication extends AnyNestedCondition {
|
||||
|
||||
ReactiveUserDetailsServiceCondition() {
|
||||
RSocketEnabledOrReactiveWebApplication() {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ -116,4 +116,29 @@ public class ReactiveUserDetailsServiceAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
static final class MissingAlternativeOrUserPropertiesConfigured extends AnyNestedCondition {
|
||||
|
||||
MissingAlternativeOrUserPropertiesConfigured() {
|
||||
super(ConfigurationPhase.PARSE_CONFIGURATION);
|
||||
}
|
||||
|
||||
@ConditionalOnMissingClass({
|
||||
"org.springframework.security.oauth2.client.registration.ClientRegistrationRepository",
|
||||
"org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector" })
|
||||
static final class MissingAlternative {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(prefix = "spring.security.user", name = "name")
|
||||
static final class NameConfigured {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(prefix = "spring.security.user", name = "password")
|
||||
static final class PasswordConfigured {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -25,12 +25,16 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
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.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration.MissingAlternativeOrUserPropertiesConfigured;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationManagerResolver;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
@ -53,9 +57,7 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnClass(AuthenticationManager.class)
|
||||
@ConditionalOnMissingClass({ "org.springframework.security.oauth2.client.registration.ClientRegistrationRepository",
|
||||
"org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector",
|
||||
"org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository" })
|
||||
@Conditional(MissingAlternativeOrUserPropertiesConfigured.class)
|
||||
@ConditionalOnBean(ObjectPostProcessor.class)
|
||||
@ConditionalOnMissingBean(value = { AuthenticationManager.class, AuthenticationProvider.class, UserDetailsService.class,
|
||||
AuthenticationManagerResolver.class }, type = "org.springframework.security.oauth2.jwt.JwtDecoder")
|
||||
@ -93,4 +95,30 @@ public class UserDetailsServiceAutoConfiguration {
|
||||
return NOOP_PASSWORD_PREFIX + password;
|
||||
}
|
||||
|
||||
static final class MissingAlternativeOrUserPropertiesConfigured extends AnyNestedCondition {
|
||||
|
||||
MissingAlternativeOrUserPropertiesConfigured() {
|
||||
super(ConfigurationPhase.PARSE_CONFIGURATION);
|
||||
}
|
||||
|
||||
@ConditionalOnMissingClass({
|
||||
"org.springframework.security.oauth2.client.registration.ClientRegistrationRepository",
|
||||
"org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector",
|
||||
"org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository" })
|
||||
static final class MissingAlternative {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(prefix = "spring.security.user", name = "name")
|
||||
static final class NameConfigured {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(prefix = "spring.security.user", name = "password")
|
||||
static final class PasswordConfigured {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -121,6 +121,18 @@ class ReactiveUserDetailsServiceAutoConfigurationTests {
|
||||
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(ReactiveUserDetailsService.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void configuresDefaultUserWhenResourceServerIsPresentAndUsernameIsConfigured() {
|
||||
this.contextRunner.withPropertyValues("spring.security.user.name=carol")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ReactiveUserDetailsService.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void configuresDefaultUserWhenResourceServerIsPresentAndPasswordIsConfigured() {
|
||||
this.contextRunner.withPropertyValues("spring.security.user.password=p4ssw0rd")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ReactiveUserDetailsService.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void userDetailsServiceWhenPasswordEncoderAbsentAndDefaultPassword() {
|
||||
this.contextRunner
|
||||
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,8 +23,10 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.test.system.CapturedOutput;
|
||||
@ -176,6 +178,23 @@ class UserDetailsServiceAutoConfigurationTests {
|
||||
.run(((context) -> assertThat(context).doesNotHaveBean(InMemoryUserDetailsManager.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void userDetailsServiceWhenRelyingPartyRegistrationRepositoryPresentAndUsernameConfigured() {
|
||||
this.contextRunner
|
||||
.withClassLoader(new FilteredClassLoader(ClientRegistrationRepository.class, OpaqueTokenIntrospector.class))
|
||||
.withPropertyValues("spring.security.user.name=alice")
|
||||
.withInitializer(ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.INFO))
|
||||
.run(((context) -> assertThat(context).hasSingleBean(InMemoryUserDetailsManager.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void userDetailsServiceWhenRelyingPartyRegistrationRepositoryPresentAndPasswordConfigured() {
|
||||
this.contextRunner
|
||||
.withClassLoader(new FilteredClassLoader(ClientRegistrationRepository.class, OpaqueTokenIntrospector.class))
|
||||
.withPropertyValues("spring.security.user.password=secret")
|
||||
.run(((context) -> assertThat(context).hasSingleBean(InMemoryUserDetailsManager.class)));
|
||||
}
|
||||
|
||||
private Function<ApplicationContextRunner, ApplicationContextRunner> noOtherFormsOfAuthenticationOnTheClasspath() {
|
||||
return (contextRunner) -> contextRunner
|
||||
.withClassLoader(new FilteredClassLoader(ClientRegistrationRepository.class, OpaqueTokenIntrospector.class,
|
||||
|
Loading…
Reference in New Issue
Block a user