|
@@ -24,6 +24,7 @@ import org.springframework.security.authentication.encoding.PlaintextPasswordEnc
|
|
import org.springframework.security.core.AuthenticationException;
|
|
import org.springframework.security.core.AuthenticationException;
|
|
import org.springframework.security.core.userdetails.UserDetails;
|
|
import org.springframework.security.core.userdetails.UserDetails;
|
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
|
|
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|
import org.springframework.dao.DataAccessException;
|
|
import org.springframework.dao.DataAccessException;
|
|
import org.springframework.util.Assert;
|
|
import org.springframework.util.Assert;
|
|
|
|
|
|
@@ -32,12 +33,27 @@ import org.springframework.util.Assert;
|
|
* from an {@link UserDetailsService}.
|
|
* from an {@link UserDetailsService}.
|
|
*
|
|
*
|
|
* @author Ben Alex
|
|
* @author Ben Alex
|
|
|
|
+ * @author Rob Winch
|
|
*/
|
|
*/
|
|
public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
|
|
public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
|
|
|
|
+ //~ Static fields/initializers =====================================================================================
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The plaintext password used to perform {@link PasswordEncoder#isPasswordValid(String, String, Object)} on when the user is
|
|
|
|
+ * not found to avoid SEC-2056.
|
|
|
|
+ */
|
|
|
|
+ private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";
|
|
|
|
|
|
//~ Instance fields ================================================================================================
|
|
//~ Instance fields ================================================================================================
|
|
|
|
|
|
- private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
|
|
|
|
|
|
+ private PasswordEncoder passwordEncoder;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The password used to perform {@link PasswordEncoder#isPasswordValid(String, String, Object)} on when the user is
|
|
|
|
+ * not found to avoid SEC-2056. This is necessary, because some {@link PasswordEncoder} implementations will short circuit if the
|
|
|
|
+ * password is not in a valid format.
|
|
|
|
+ */
|
|
|
|
+ private String userNotFoundEncodedPassword;
|
|
|
|
|
|
private SaltSource saltSource;
|
|
private SaltSource saltSource;
|
|
|
|
|
|
@@ -45,8 +61,13 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
|
|
|
|
|
|
private boolean includeDetailsObject = true;
|
|
private boolean includeDetailsObject = true;
|
|
|
|
|
|
|
|
+ public DaoAuthenticationProvider() {
|
|
|
|
+ setPasswordEncoder(new PlaintextPasswordEncoder());
|
|
|
|
+ }
|
|
|
|
+
|
|
//~ Methods ========================================================================================================
|
|
//~ Methods ========================================================================================================
|
|
|
|
|
|
|
|
+ @SuppressWarnings("deprecation")
|
|
protected void additionalAuthenticationChecks(UserDetails userDetails,
|
|
protected void additionalAuthenticationChecks(UserDetails userDetails,
|
|
UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
|
|
UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
|
|
Object salt = null;
|
|
Object salt = null;
|
|
@@ -88,6 +109,13 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
|
|
catch (DataAccessException repositoryProblem) {
|
|
catch (DataAccessException repositoryProblem) {
|
|
throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
|
|
throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
|
|
}
|
|
}
|
|
|
|
+ catch (UsernameNotFoundException notFound) {
|
|
|
|
+ if(authentication.getCredentials() != null) {
|
|
|
|
+ String presentedPassword = authentication.getCredentials().toString();
|
|
|
|
+ passwordEncoder.isPasswordValid(userNotFoundEncodedPassword, presentedPassword, null);
|
|
|
|
+ }
|
|
|
|
+ throw notFound;
|
|
|
|
+ }
|
|
|
|
|
|
if (loadedUser == null) {
|
|
if (loadedUser == null) {
|
|
throw new AuthenticationServiceException(
|
|
throw new AuthenticationServiceException(
|
|
@@ -103,6 +131,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
|
|
* @param passwordEncoder The passwordEncoder to use
|
|
* @param passwordEncoder The passwordEncoder to use
|
|
*/
|
|
*/
|
|
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
|
|
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
|
|
|
|
+ this.userNotFoundEncodedPassword = passwordEncoder.encodePassword(USER_NOT_FOUND_PASSWORD, null);
|
|
this.passwordEncoder = passwordEncoder;
|
|
this.passwordEncoder = passwordEncoder;
|
|
}
|
|
}
|
|
|
|
|