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