Ver código fonte

Remove deprecated elements from DaoAuthenticationProvider

Closes gh-17298

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
Tran Ngoc Nhan 2 meses atrás
pai
commit
242956a63c
13 arquivos alterados com 76 adições e 136 exclusões
  1. 5 2
      config/src/main/java/org/springframework/security/config/authentication/AbstractUserDetailsServiceBeanDefinitionParser.java
  2. 5 2
      config/src/main/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParser.java
  3. 2 3
      config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java
  4. 2 4
      config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java
  5. 2 3
      config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java
  6. 3 3
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java
  7. 2 3
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.java
  8. 1 1
      config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-Sec750.xml
  9. 1 30
      core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java
  10. 45 75
      core/src/test/java/org/springframework/security/authentication/dao/DaoAuthenticationProviderTests.java
  11. 2 3
      core/src/test/java/org/springframework/security/provisioning/InMemoryUserDetailsManagerTests.java
  12. 3 4
      docs/modules/ROOT/pages/servlet/authentication/passwords/index.adoc
  13. 3 3
      itest/context/src/integration-test/resources/filter-chain-performance-app-context.xml

+ 5 - 2
config/src/main/java/org/springframework/security/config/authentication/AbstractUserDetailsServiceBeanDefinitionParser.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2025 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,6 +20,7 @@ import org.w3c.dom.Element;
 
 import org.springframework.beans.factory.BeanDefinitionStoreException;
 import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
 import org.springframework.beans.factory.config.RuntimeBeanReference;
 import org.springframework.beans.factory.parsing.BeanComponentDefinition;
 import org.springframework.beans.factory.support.AbstractBeanDefinition;
@@ -73,8 +74,10 @@ public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements
 			if (!StringUtils.hasText(id)) {
 				id = pc.getReaderContext().generateBeanName(definition);
 			}
+			ValueHolder userDetailsServiceValueHolder = new ValueHolder(new RuntimeBeanReference(id));
+			userDetailsServiceValueHolder.setName("userDetailsService");
 			BeanDefinition container = pc.getContainingBeanDefinition();
-			container.getPropertyValues().add("userDetailsService", new RuntimeBeanReference(id));
+			container.getConstructorArgumentValues().addGenericArgumentValue(userDetailsServiceValueHolder);
 		}
 		if (StringUtils.hasText(id)) {
 			return id;

+ 5 - 2
config/src/main/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParser.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2025 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,6 +20,7 @@ import org.w3c.dom.Element;
 
 import org.springframework.beans.BeanMetadataElement;
 import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
 import org.springframework.beans.factory.config.RuntimeBeanReference;
 import org.springframework.beans.factory.support.RootBeanDefinition;
 import org.springframework.beans.factory.xml.BeanDefinitionParser;
@@ -64,7 +65,9 @@ public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitio
 							+ "elements '" + Elements.USER_SERVICE + "', '" + Elements.JDBC_USER_SERVICE + "' or '"
 							+ Elements.LDAP_USER_SERVICE + "'", element);
 			}
-			authProvider.getPropertyValues().add("userDetailsService", new RuntimeBeanReference(ref));
+			ValueHolder userDetailsServiceValueHolder = new ValueHolder(new RuntimeBeanReference(ref));
+			userDetailsServiceValueHolder.setName("userDetailsService");
+			authProvider.getConstructorArgumentValues().addGenericArgumentValue(userDetailsServiceValueHolder);
 		}
 		else {
 			// Use the child elements to create the UserDetailsService

+ 2 - 3
config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -241,8 +241,7 @@ public class AuthenticationManagerBuilderTests {
 
 		@Bean
 		AuthenticationProvider authenticationProvider() throws Exception {
-			DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-			provider.setUserDetailsService(userDetailsService());
+			DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService());
 			return provider;
 		}
 

+ 2 - 4
config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -74,9 +74,7 @@ public class NamespaceAuthenticationProviderTests {
 
 		@Bean
 		DaoAuthenticationProvider authenticationProvider() {
-			DaoAuthenticationProvider result = new DaoAuthenticationProvider();
-			result.setUserDetailsService(new InMemoryUserDetailsManager(PasswordEncodedUser.user()));
-			return result;
+			return new DaoAuthenticationProvider(new InMemoryUserDetailsManager(PasswordEncodedUser.user()));
 		}
 
 	}

+ 2 - 3
config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -503,8 +503,7 @@ public class AuthenticationConfigurationTests {
 			UserDetails user = User.withUserDetails(PasswordEncodedUser.user()).username("boot").build();
 			List<UserDetails> users = Arrays.asList(user);
 			InMemoryUserDetailsManager inMemory = new InMemoryUserDetailsManager(users);
-			DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-			provider.setUserDetailsService(inMemory);
+			DaoAuthenticationProvider provider = new DaoAuthenticationProvider(inMemory);
 			auth.authenticationProvider(provider);
 		}
 

+ 3 - 3
config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2023 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -376,8 +376,8 @@ public class RememberMeConfigurerTests {
 		@Autowired
 		void configure(AuthenticationManagerBuilder auth) {
 			User user = (User) PasswordEncodedUser.user();
-			DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-			provider.setUserDetailsService(new InMemoryUserDetailsManager(Collections.singletonList(user)));
+			DaoAuthenticationProvider provider = new DaoAuthenticationProvider(
+					new InMemoryUserDetailsManager(Collections.singletonList(user)));
 			// @formatter:off
 			auth
 				.authenticationProvider(provider);

+ 2 - 3
config/src/test/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -269,8 +269,7 @@ public class ServletApiConfigurerTests {
 
 		@Bean
 		AuthenticationManager customAuthenticationManager(UserDetailsService userDetailsService) {
-			DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-			provider.setUserDetailsService(userDetailsService);
+			DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
 			return provider::authenticate;
 		}
 

+ 1 - 1
config/src/test/resources/org/springframework/security/config/http/MiscHttpConfigTests-Sec750.xml

@@ -34,7 +34,7 @@
 	</authentication-manager>
 
 	<b:bean name="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
-		<b:property name="userDetailsService" ref="userService"/>
+		<b:constructor-arg name="userDetailsService" ref="userService"/>
 	</b:bean>
 
 	<b:bean name="userService" class="org.mockito.Mockito" factory-method="mock">

+ 1 - 30
core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java

@@ -68,31 +68,11 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
 
 	private CompromisedPasswordChecker compromisedPasswordChecker;
 
-	/**
-	 * @deprecated Please provide the {@link UserDetailsService} in the constructor
-	 */
-	@Deprecated
-	public DaoAuthenticationProvider() {
-	}
-
 	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);
+		this.userDetailsService = userDetailsService;
 	}
 
 	@Override
-	@SuppressWarnings("deprecation")
 	protected void additionalAuthenticationChecks(UserDetails userDetails,
 			UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
 		if (authentication.getCredentials() == null) {
@@ -185,15 +165,6 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
 		return this.passwordEncoder.get();
 	}
 
-	/**
-	 * @param userDetailsService
-	 * @deprecated Please provide the {@link UserDetailsService} in the constructor
-	 */
-	@Deprecated
-	public void setUserDetailsService(UserDetailsService userDetailsService) {
-		this.userDetailsService = userDetailsService;
-	}
-
 	protected UserDetailsService getUserDetailsService() {
 		return this.userDetailsService;
 	}

+ 45 - 75
core/src/test/java/org/springframework/security/authentication/dao/DaoAuthenticationProviderTests.java

@@ -80,8 +80,7 @@ public class DaoAuthenticationProviderTests {
 	@Test
 	public void testAuthenticateFailsForIncorrectPasswordCase() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("rod", "KOala");
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		provider.setUserCache(new MockUserCache());
 		assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> provider.authenticate(token));
 	}
@@ -89,8 +88,7 @@ public class DaoAuthenticationProviderTests {
 	@Test
 	public void testReceivedBadCredentialsWhenCredentialsNotProvided() {
 		// Test related to SEC-434
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		provider.setUserCache(new MockUserCache());
 		UsernamePasswordAuthenticationToken authenticationToken = UsernamePasswordAuthenticationToken
 			.unauthenticated("rod", null);
@@ -102,8 +100,7 @@ public class DaoAuthenticationProviderTests {
 	public void testAuthenticateFailsIfAccountExpired() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("peter",
 				"opal");
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserPeterAccountExpired());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserPeterAccountExpired());
 		provider.setUserCache(new MockUserCache());
 		assertThatExceptionOfType(AccountExpiredException.class).isThrownBy(() -> provider.authenticate(token));
 	}
@@ -112,16 +109,14 @@ public class DaoAuthenticationProviderTests {
 	public void testAuthenticateFailsIfAccountLocked() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("peter",
 				"opal");
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserPeterAccountLocked());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserPeterAccountLocked());
 		provider.setUserCache(new MockUserCache());
 		assertThatExceptionOfType(LockedException.class).isThrownBy(() -> provider.authenticate(token));
 	}
 
 	@Test
 	public void testAuthenticateFailsIfCredentialsExpired() {
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserPeterCredentialsExpired());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserPeterCredentialsExpired());
 		provider.setUserCache(new MockUserCache());
 		assertThatExceptionOfType(CredentialsExpiredException.class).isThrownBy(
 				() -> provider.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("peter", "opal")));
@@ -135,8 +130,7 @@ public class DaoAuthenticationProviderTests {
 	public void testAuthenticateFailsIfUserDisabled() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("peter",
 				"opal");
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserPeter());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserPeter());
 		provider.setUserCache(new MockUserCache());
 		assertThatExceptionOfType(DisabledException.class).isThrownBy(() -> provider.authenticate(token));
 	}
@@ -144,8 +138,7 @@ public class DaoAuthenticationProviderTests {
 	@Test
 	public void testAuthenticateFailsWhenAuthenticationDaoHasBackendFailure() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("rod", "koala");
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceSimulateBackendError());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceSimulateBackendError());
 		provider.setUserCache(new MockUserCache());
 		assertThatExceptionOfType(InternalAuthenticationServiceException.class)
 			.isThrownBy(() -> provider.authenticate(token));
@@ -154,8 +147,7 @@ public class DaoAuthenticationProviderTests {
 	@Test
 	public void testAuthenticateFailsWithEmptyUsername() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated(null, "koala");
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		provider.setUserCache(new MockUserCache());
 		assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> provider.authenticate(token));
 	}
@@ -164,8 +156,7 @@ public class DaoAuthenticationProviderTests {
 	public void testAuthenticateFailsWithInvalidPassword() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("rod",
 				"INVALID_PASSWORD");
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		provider.setUserCache(new MockUserCache());
 		assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> provider.authenticate(token));
 	}
@@ -174,10 +165,9 @@ public class DaoAuthenticationProviderTests {
 	public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionFalse() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("INVALID_USER",
 				"koala");
-		DaoAuthenticationProvider provider = createProvider();
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		provider.setHideUserNotFoundExceptions(false); // we want
 														// UsernameNotFoundExceptions
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
 		provider.setUserCache(new MockUserCache());
 		assertThatExceptionOfType(UsernameNotFoundException.class).isThrownBy(() -> provider.authenticate(token));
 	}
@@ -186,9 +176,8 @@ public class DaoAuthenticationProviderTests {
 	public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionsWithDefaultOfTrue() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("INVALID_USER",
 				"koala");
-		DaoAuthenticationProvider provider = createProvider();
-		assertThat(provider.isHideUserNotFoundExceptions()).isTrue();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
+		assertThat(createProvider(null).isHideUserNotFoundExceptions()).isTrue();
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		provider.setUserCache(new MockUserCache());
 		assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> provider.authenticate(token));
 	}
@@ -197,9 +186,8 @@ public class DaoAuthenticationProviderTests {
 	public void testAuthenticateFailsWithInvalidUsernameAndChangePasswordEncoder() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("INVALID_USER",
 				"koala");
-		DaoAuthenticationProvider provider = createProvider();
-		assertThat(provider.isHideUserNotFoundExceptions()).isTrue();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
+		assertThat(createProvider(null).isHideUserNotFoundExceptions()).isTrue();
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		provider.setUserCache(new MockUserCache());
 		assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> provider.authenticate(token));
 		provider.setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
@@ -209,8 +197,7 @@ public class DaoAuthenticationProviderTests {
 	@Test
 	public void testAuthenticateFailsWithMixedCaseUsernameIfDefaultChanged() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("RoD", "koala");
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		provider.setUserCache(new MockUserCache());
 		assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> provider.authenticate(token));
 	}
@@ -219,8 +206,7 @@ public class DaoAuthenticationProviderTests {
 	public void testAuthenticates() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("rod", "koala");
 		token.setDetails("192.168.0.1");
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		provider.setUserCache(new MockUserCache());
 		Authentication result = provider.authenticate(token);
 		if (!(result instanceof UsernamePasswordAuthenticationToken)) {
@@ -236,8 +222,7 @@ public class DaoAuthenticationProviderTests {
 	@Test
 	public void testAuthenticatesASecondTime() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("rod", "koala");
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		provider.setUserCache(new MockUserCache());
 		Authentication result = provider.authenticate(token);
 		if (!(result instanceof UsernamePasswordAuthenticationToken)) {
@@ -254,8 +239,7 @@ public class DaoAuthenticationProviderTests {
 	@Test
 	public void testAuthenticatesWithForcePrincipalAsString() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("rod", "koala");
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		provider.setUserCache(new MockUserCache());
 		provider.setForcePrincipalAsString(true);
 		Authentication result = provider.authenticate(token);
@@ -276,9 +260,8 @@ public class DaoAuthenticationProviderTests {
 		PasswordEncoder encoder = mock(PasswordEncoder.class);
 		UserDetailsService userDetailsService = mock(UserDetailsService.class);
 		UserDetailsPasswordService passwordManager = mock(UserDetailsPasswordService.class);
-		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
 		provider.setPasswordEncoder(encoder);
-		provider.setUserDetailsService(userDetailsService);
 		provider.setUserDetailsPasswordService(passwordManager);
 		UserDetails user = PasswordEncodedUser.user();
 		given(encoder.matches(any(), any())).willReturn(true);
@@ -298,9 +281,8 @@ public class DaoAuthenticationProviderTests {
 		PasswordEncoder encoder = mock(PasswordEncoder.class);
 		UserDetailsService userDetailsService = mock(UserDetailsService.class);
 		UserDetailsPasswordService passwordManager = mock(UserDetailsPasswordService.class);
-		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
 		provider.setPasswordEncoder(encoder);
-		provider.setUserDetailsService(userDetailsService);
 		provider.setUserDetailsPasswordService(passwordManager);
 		UserDetails user = PasswordEncodedUser.user();
 		given(encoder.matches(any(), any())).willReturn(false);
@@ -316,9 +298,8 @@ public class DaoAuthenticationProviderTests {
 		PasswordEncoder encoder = mock(PasswordEncoder.class);
 		UserDetailsService userDetailsService = mock(UserDetailsService.class);
 		UserDetailsPasswordService passwordManager = mock(UserDetailsPasswordService.class);
-		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
 		provider.setPasswordEncoder(encoder);
-		provider.setUserDetailsService(userDetailsService);
 		provider.setUserDetailsPasswordService(passwordManager);
 		UserDetails user = PasswordEncodedUser.user();
 		given(encoder.matches(any(), any())).willReturn(true);
@@ -331,15 +312,14 @@ public class DaoAuthenticationProviderTests {
 	@Test
 	public void testDetectsNullBeingReturnedFromAuthenticationDao() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("rod", "koala");
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceReturnsNull());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceReturnsNull());
 		assertThatExceptionOfType(AuthenticationServiceException.class).isThrownBy(() -> provider.authenticate(token))
 			.withMessage("UserDetailsService returned null, which is an interface contract violation");
 	}
 
 	@Test
 	public void testGettersSetters() {
-		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(null);
 		provider.setPasswordEncoder(new BCryptPasswordEncoder());
 		assertThat(provider.getPasswordEncoder().getClass()).isEqualTo(BCryptPasswordEncoder.class);
 		provider.setUserCache(new SpringCacheBasedUserCache(mock(Cache.class)));
@@ -354,8 +334,7 @@ public class DaoAuthenticationProviderTests {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("rod", "koala");
 		MockUserDetailsServiceUserRod authenticationDao = new MockUserDetailsServiceUserRod();
 		MockUserCache cache = new MockUserCache();
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(authenticationDao);
+		DaoAuthenticationProvider provider = createProvider(authenticationDao);
 		provider.setUserCache(cache);
 		// This will work, as password still "koala"
 		provider.authenticate(token);
@@ -373,14 +352,13 @@ public class DaoAuthenticationProviderTests {
 
 	@Test
 	public void testStartupFailsIfNoAuthenticationDao() throws Exception {
-		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(null);
 		assertThatIllegalArgumentException().isThrownBy(provider::afterPropertiesSet);
 	}
 
 	@Test
 	public void testStartupFailsIfNoUserCacheSet() throws Exception {
-		DaoAuthenticationProvider provider = createProvider();
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		assertThat(provider.getUserCache().getClass()).isEqualTo(NullUserCache.class);
 		provider.setUserCache(null);
 		assertThatIllegalArgumentException().isThrownBy(provider::afterPropertiesSet);
@@ -388,9 +366,8 @@ public class DaoAuthenticationProviderTests {
 
 	@Test
 	public void testStartupSuccess() throws Exception {
-		DaoAuthenticationProvider provider = createProvider();
 		UserDetailsService userDetailsService = new MockUserDetailsServiceUserRod();
-		provider.setUserDetailsService(userDetailsService);
+		DaoAuthenticationProvider provider = createProvider(userDetailsService);
 		provider.setUserCache(new MockUserCache());
 		assertThat(provider.getUserDetailsService()).isEqualTo(userDetailsService);
 		provider.afterPropertiesSet();
@@ -398,7 +375,7 @@ public class DaoAuthenticationProviderTests {
 
 	@Test
 	public void testSupports() {
-		DaoAuthenticationProvider provider = createProvider();
+		DaoAuthenticationProvider provider = createProvider(null);
 		assertThat(provider.supports(UsernamePasswordAuthenticationToken.class)).isTrue();
 		assertThat(!provider.supports(TestingAuthenticationToken.class)).isTrue();
 	}
@@ -410,10 +387,9 @@ public class DaoAuthenticationProviderTests {
 				"koala");
 		PasswordEncoder encoder = mock(PasswordEncoder.class);
 		given(encoder.encode(anyString())).willReturn("koala");
-		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(new MockUserDetailsServiceUserRod());
 		provider.setHideUserNotFoundExceptions(false);
 		provider.setPasswordEncoder(encoder);
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
 		provider.afterPropertiesSet();
 		assertThatExceptionOfType(UsernameNotFoundException.class).isThrownBy(() -> provider.authenticate(token));
 		// ensure encoder invoked w/ non-null strings since PasswordEncoder impls may fail
@@ -426,12 +402,11 @@ public class DaoAuthenticationProviderTests {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("missing",
 				"koala");
 		PasswordEncoder encoder = new BCryptPasswordEncoder();
-		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-		provider.setHideUserNotFoundExceptions(false);
-		provider.setPasswordEncoder(encoder);
 		MockUserDetailsServiceUserRod userDetailsService = new MockUserDetailsServiceUserRod();
 		userDetailsService.password = encoder.encode((CharSequence) token.getCredentials());
-		provider.setUserDetailsService(userDetailsService);
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
+		provider.setHideUserNotFoundExceptions(false);
+		provider.setPasswordEncoder(encoder);
 		assertThatExceptionOfType(UsernameNotFoundException.class).isThrownBy(() -> provider.authenticate(token));
 	}
 
@@ -439,16 +414,15 @@ public class DaoAuthenticationProviderTests {
 	public void testUserNotFoundDefaultEncoder() {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("missing",
 				null);
-		DaoAuthenticationProvider provider = createProvider();
+		DaoAuthenticationProvider provider = createProvider(new MockUserDetailsServiceUserRod());
 		provider.setHideUserNotFoundExceptions(false);
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
 		assertThatExceptionOfType(UsernameNotFoundException.class).isThrownBy(() -> provider.authenticate(token));
 	}
 
 	@Test
 	public void constructWhenPasswordEncoderProvidedThenSets() {
-		DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(
-				NoOpPasswordEncoder.getInstance());
+		DaoAuthenticationProvider daoAuthenticationProvider = createProvider(null);
+		daoAuthenticationProvider.setPasswordEncoder(NoOpPasswordEncoder.getInstance());
 		assertThat(daoAuthenticationProvider.getPasswordEncoder()).isSameAs(NoOpPasswordEncoder.getInstance());
 	}
 
@@ -463,12 +437,11 @@ public class DaoAuthenticationProviderTests {
 		UsernamePasswordAuthenticationToken notFoundUser = UsernamePasswordAuthenticationToken
 			.unauthenticated("notFound", "koala");
 		PasswordEncoder encoder = new BCryptPasswordEncoder(10, new SecureRandom());
-		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-		provider.setHideUserNotFoundExceptions(false);
-		provider.setPasswordEncoder(encoder);
 		MockUserDetailsServiceUserRod userDetailsService = new MockUserDetailsServiceUserRod();
 		userDetailsService.password = encoder.encode((CharSequence) foundUser.getCredentials());
-		provider.setUserDetailsService(userDetailsService);
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
+		provider.setHideUserNotFoundExceptions(false);
+		provider.setPasswordEncoder(encoder);
 		int sampleSize = 100;
 		List<Long> userFoundTimes = new ArrayList<>(sampleSize);
 		for (int i = 0; i < sampleSize; i++) {
@@ -500,24 +473,22 @@ public class DaoAuthenticationProviderTests {
 		UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("missing",
 				null);
 		PasswordEncoder encoder = mock(PasswordEncoder.class);
-		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(new MockUserDetailsServiceUserRod());
 		provider.setHideUserNotFoundExceptions(false);
 		provider.setPasswordEncoder(encoder);
-		provider.setUserDetailsService(new MockUserDetailsServiceUserRod());
 		assertThatExceptionOfType(UsernameNotFoundException.class).isThrownBy(() -> provider.authenticate(token));
 		verify(encoder, times(0)).matches(anyString(), anyString());
 	}
 
 	@Test
 	void authenticateWhenPasswordLeakedThenException() {
-		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-		provider.setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
 		UserDetails user = User.withDefaultPasswordEncoder()
 			.username("user")
 			.password("password")
 			.roles("USER")
 			.build();
-		provider.setUserDetailsService(withUsers(user));
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(withUsers(user));
+		provider.setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
 		provider.setCompromisedPasswordChecker(new TestCompromisedPasswordChecker());
 		assertThatExceptionOfType(CompromisedPasswordException.class).isThrownBy(
 				() -> provider.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password")))
@@ -526,14 +497,13 @@ public class DaoAuthenticationProviderTests {
 
 	@Test
 	void authenticateWhenPasswordNotLeakedThenNoException() {
-		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-		provider.setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
 		UserDetails user = User.withDefaultPasswordEncoder()
 			.username("user")
 			.password("strongpassword")
 			.roles("USER")
 			.build();
-		provider.setUserDetailsService(withUsers(user));
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(withUsers(user));
+		provider.setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
 		provider.setCompromisedPasswordChecker(new TestCompromisedPasswordChecker());
 		Authentication authentication = provider
 			.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "strongpassword"));
@@ -544,8 +514,8 @@ public class DaoAuthenticationProviderTests {
 		return new InMemoryUserDetailsManager(users);
 	}
 
-	private DaoAuthenticationProvider createProvider() {
-		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+	private DaoAuthenticationProvider createProvider(UserDetailsService userDetailsService) {
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
 		provider.setPasswordEncoder(NoOpPasswordEncoder.getInstance());
 		return provider;
 	}

+ 2 - 3
core/src/test/java/org/springframework/security/provisioning/InMemoryUserDetailsManagerTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -167,8 +167,7 @@ public class InMemoryUserDetailsManagerTests {
 		UserDetails user = User.builder().username(username).password(password).roles("USER").build();
 		InMemoryUserDetailsManager userManager = new InMemoryUserDetailsManager(user);
 
-		DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
-		authenticationProvider.setUserDetailsService(userManager);
+		DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(userManager);
 		authenticationProvider.setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
 
 		AuthenticationManager authManager = new ProviderManager(authenticationProvider);

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

@@ -185,7 +185,7 @@ XML::
 			class="org.springframework.security.authentication.ProviderManager">
 		<constructor-arg>
 			<bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
-				<property name="userDetailsService" ref="userDetailsService" />
+				<constructor-arg name="userDetailsService" ref="userDetailsService" />
 				<property name="passwordEncoder" ref="passwordEncoder" />
 			</bean>
 		</constructor-arg>
@@ -416,8 +416,7 @@ public class SecurityConfig {
 	}
 
 	private AuthenticationManager authenticationManager() {
-		DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
-		authenticationProvider.setUserDetailsService(userDetailsService());
+		DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(userDetailsService());
 		authenticationProvider.setPasswordEncoder(passwordEncoder());
 
 		ProviderManager providerManager = new ProviderManager(authenticationProvider);
@@ -456,7 +455,7 @@ XML::
 			class="org.springframework.security.authentication.ProviderManager">
 		<constructor-arg>
 			<bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
-				<property name="userDetailsService" ref="userDetailsService" />
+				<constructor-arg name="userDetailsService" ref="userDetailsService" />
 				<property name="passwordEncoder" ref="passwordEncoder" />
 			</bean>
 		</constructor-arg>

+ 3 - 3
itest/context/src/integration-test/resources/filter-chain-performance-app-context.xml

@@ -25,9 +25,9 @@
 	<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
 		<constructor-arg>
 			<list>
-			   <bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
-				   <property name="userDetailsService" ref="userService"/>
-			   </bean>
+				<bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
+					<constructor-arg name="userDetailsService" ref="userService" />
+				</bean>
 			</list>
 		</constructor-arg>
 	</bean>