2
0
Эх сурвалжийг харах

Add UserDetailsService Constructor

Closes gh-15973
Josh Cummings 10 сар өмнө
parent
commit
b9f3a28678

+ 2 - 6
config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeUserDetailsBeanManagerConfigurer.java

@@ -95,14 +95,10 @@ class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationCon
 			PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
 			UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class);
 			CompromisedPasswordChecker passwordChecker = getBeanOrNull(CompromisedPasswordChecker.class);
-			DaoAuthenticationProvider provider;
+			DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
 			if (passwordEncoder != null) {
-				provider = new DaoAuthenticationProvider(passwordEncoder);
+				provider.setPasswordEncoder(passwordEncoder);
 			}
-			else {
-				provider = new DaoAuthenticationProvider();
-			}
-			provider.setUserDetailsService(userDetailsService);
 			if (passwordManager != null) {
 				provider.setUserDetailsPasswordService(passwordManager);
 			}

+ 2 - 2
config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/AbstractDaoAuthenticationConfigurer.java

@@ -36,7 +36,7 @@ import org.springframework.security.crypto.password.PasswordEncoder;
 public abstract class AbstractDaoAuthenticationConfigurer<B extends ProviderManagerBuilder<B>, C extends AbstractDaoAuthenticationConfigurer<B, C, U>, U extends UserDetailsService>
 		extends UserDetailsAwareConfigurer<B, U> {
 
-	private DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+	private DaoAuthenticationProvider provider;
 
 	private final U userDetailsService;
 
@@ -46,7 +46,7 @@ public abstract class AbstractDaoAuthenticationConfigurer<B extends ProviderMana
 	 */
 	AbstractDaoAuthenticationConfigurer(U userDetailsService) {
 		this.userDetailsService = userDetailsService;
-		this.provider.setUserDetailsService(userDetailsService);
+		this.provider = new DaoAuthenticationProvider(userDetailsService);
 		if (userDetailsService instanceof UserDetailsPasswordService) {
 			this.provider.setUserDetailsPasswordService((UserDetailsPasswordService) userDetailsService);
 		}

+ 1 - 2
config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java

@@ -65,8 +65,7 @@ public class AuthenticationManagerFactoryBean implements FactoryBean<Authenticat
 			if (uds == null) {
 				throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER, MISSING_BEAN_ERROR_MESSAGE);
 			}
-			DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-			provider.setUserDetailsService(uds);
+			DaoAuthenticationProvider provider = new DaoAuthenticationProvider(uds);
 			PasswordEncoder passwordEncoder = this.bf.getBeanProvider(PasswordEncoder.class).getIfUnique();
 			if (passwordEncoder != null) {
 				provider.setPasswordEncoder(passwordEncoder);

+ 28 - 9
core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java

@@ -16,6 +16,8 @@
 
 package org.springframework.security.authentication.dao;
 
+import java.util.function.Supplier;
+
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.authentication.InternalAuthenticationServiceException;
@@ -31,6 +33,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.security.crypto.factory.PasswordEncoderFactories;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.util.Assert;
+import org.springframework.util.function.SingletonSupplier;
 
 /**
  * An {@link AuthenticationProvider} implementation that retrieves user details from a
@@ -48,7 +51,8 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
 	 */
 	private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";
 
-	private PasswordEncoder passwordEncoder;
+	private Supplier<PasswordEncoder> passwordEncoder = SingletonSupplier
+		.of(PasswordEncoderFactories::createDelegatingPasswordEncoder);
 
 	/**
 	 * The password used to perform {@link PasswordEncoder#matches(CharSequence, String)}
@@ -64,15 +68,25 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
 
 	private CompromisedPasswordChecker compromisedPasswordChecker;
 
+	/**
+	 * @deprecated Please provide the {@link UserDetailsService} in the constructor
+	 */
+	@Deprecated
 	public DaoAuthenticationProvider() {
-		this(PasswordEncoderFactories.createDelegatingPasswordEncoder());
+	}
+
+	public DaoAuthenticationProvider(UserDetailsService userDetailsService) {
+		setUserDetailsService(userDetailsService);
 	}
 
 	/**
 	 * Creates a new instance using the provided {@link PasswordEncoder}
 	 * @param passwordEncoder the {@link PasswordEncoder} to use. Cannot be null.
 	 * @since 6.0.3
+	 * @deprecated Please provide the {@link UserDetailsService} in the constructor
+	 * followed by {@link #setPasswordEncoder(PasswordEncoder)} instead
 	 */
+	@Deprecated
 	public DaoAuthenticationProvider(PasswordEncoder passwordEncoder) {
 		setPasswordEncoder(passwordEncoder);
 	}
@@ -87,7 +101,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
 				.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
 		}
 		String presentedPassword = authentication.getCredentials().toString();
-		if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
+		if (!this.passwordEncoder.get().matches(presentedPassword, userDetails.getPassword())) {
 			this.logger.debug("Failed to authenticate since password does not match stored value");
 			throw new BadCredentialsException(this.messages
 				.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
@@ -133,9 +147,9 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
 			throw new CompromisedPasswordException("The provided password is compromised, please change your password");
 		}
 		boolean upgradeEncoding = this.userDetailsPasswordService != null
-				&& this.passwordEncoder.upgradeEncoding(user.getPassword());
+				&& this.passwordEncoder.get().upgradeEncoding(user.getPassword());
 		if (upgradeEncoding) {
-			String newPassword = this.passwordEncoder.encode(presentedPassword);
+			String newPassword = this.passwordEncoder.get().encode(presentedPassword);
 			user = this.userDetailsPasswordService.updatePassword(user, newPassword);
 		}
 		return super.createSuccessAuthentication(principal, authentication, user);
@@ -143,14 +157,14 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
 
 	private void prepareTimingAttackProtection() {
 		if (this.userNotFoundEncodedPassword == null) {
-			this.userNotFoundEncodedPassword = this.passwordEncoder.encode(USER_NOT_FOUND_PASSWORD);
+			this.userNotFoundEncodedPassword = this.passwordEncoder.get().encode(USER_NOT_FOUND_PASSWORD);
 		}
 	}
 
 	private void mitigateAgainstTimingAttack(UsernamePasswordAuthenticationToken authentication) {
 		if (authentication.getCredentials() != null) {
 			String presentedPassword = authentication.getCredentials().toString();
-			this.passwordEncoder.matches(presentedPassword, this.userNotFoundEncodedPassword);
+			this.passwordEncoder.get().matches(presentedPassword, this.userNotFoundEncodedPassword);
 		}
 	}
 
@@ -163,14 +177,19 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
 	 */
 	public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
 		Assert.notNull(passwordEncoder, "passwordEncoder cannot be null");
-		this.passwordEncoder = passwordEncoder;
+		this.passwordEncoder = () -> passwordEncoder;
 		this.userNotFoundEncodedPassword = null;
 	}
 
 	protected PasswordEncoder getPasswordEncoder() {
-		return this.passwordEncoder;
+		return this.passwordEncoder.get();
 	}
 
+	/**
+	 * @param userDetailsService
+	 * @deprecated Please provide the {@link UserDetailsService} in the constructor
+	 */
+	@Deprecated
 	public void setUserDetailsService(UserDetailsService userDetailsService) {
 		this.userDetailsService = userDetailsService;
 	}

+ 3 - 6
docs/modules/ROOT/pages/servlet/authentication/passwords/index.adoc

@@ -148,8 +148,7 @@ public class SecurityConfig {
 	public AuthenticationManager authenticationManager(
 			UserDetailsService userDetailsService,
 			PasswordEncoder passwordEncoder) {
-		DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
-		authenticationProvider.setUserDetailsService(userDetailsService);
+		DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(userDetailsService);
 		authenticationProvider.setPasswordEncoder(passwordEncoder);
 
 		return new ProviderManager(authenticationProvider);
@@ -229,8 +228,7 @@ class SecurityConfig {
 	fun authenticationManager(
 			userDetailsService: UserDetailsService,
 			passwordEncoder: PasswordEncoder): AuthenticationManager {
-		val authenticationProvider = DaoAuthenticationProvider()
-		authenticationProvider.setUserDetailsService(userDetailsService)
+		val authenticationProvider = DaoAuthenticationProvider(userDetailsService)
 		authenticationProvider.setPasswordEncoder(passwordEncoder)
 
 		return ProviderManager(authenticationProvider)
@@ -501,8 +499,7 @@ class SecurityConfig {
 
 	@Bean
 	fun authenticationManager(): AuthenticationManager {
-		val authenticationProvider = DaoAuthenticationProvider()
-		authenticationProvider.setUserDetailsService(userDetailsService())
+		val authenticationProvider = DaoAuthenticationProvider(userDetailsService())
 		authenticationProvider.setPasswordEncoder(passwordEncoder())
 
 		val providerManager = ProviderManager(authenticationProvider)