Spring Security: LockedException thrown instead of BadCredentialsException, why?

Using Spring Security 4.0.2.RELEASE

For basic user authentication using spring-security framework, I implemented spring-security DaoAuthenticationProvider

When a user tries to log in with the correct username, the wrong password and the user account is already locked , I expected the spring authentication module to throw a BadCredentialsException but instead it throws a LockedException

My questions

  • why does spring-security handle the user for further authentication while the wrong credentials are incorrect?
  • Is it good to show a message in the application that "User is blocked", even if the password for the user is invalid?
  • How do I manage to throw / catch a BadCredentialsException for an invalid password and a blocked user?

Any help would be greatly appreciated. Authentication Provider Implementation Code

 @Component("authenticationProvider") public class LoginAuthenticationProvider extends DaoAuthenticationProvider { @Autowired UserDAO userDAO; @Autowired @Qualifier("userDetailsService") @Override public void setUserDetailsService(UserDetailsService userDetailsService) { super.setUserDetailsService(userDetailsService); } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { try { Authentication auth = super.authenticate(authentication); // if reach here, means login success, else exception will be thrown // reset the user attempts userDAO.resetPasswordRetryAttempts(authentication.getName()); return auth; } catch (BadCredentialsException ex) { // invalid login, update user attempts userDAO.updatePasswordRetryAttempts(authentication.getName(), PropertyUtils.getLoginAttemptsLimit()); throw ex; } catch (LockedException ex) { // this user is locked throw ex; } catch (AccountExpiredException ex) { // this user is expired throw ex; } catch (Exception ex) { ex.printStackTrace(); throw ex; } } } 
+5
source share
1 answer

You asked:

Spring Security: LockedException thrown instead of BadCredentialsException thrown, why?

This is because spring protection will first verify that the account exists and is valid, and after that it verifies the password.

More specific: this is done in AbstractUserDetailsAuthenticationProvider.authenticate . In a very brief description, the method works as follows:

 user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); ... preAuthenticationChecks.check(user); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); ... postAuthenticationChecks.check(user); 
  • retrieveUser - load user
  • preAuthenticationChecks.check(user); - DefaultPreAuthenticationChecks : check blocked ...
  • additionalAuthenticationChecks - verifies password
  • postAuthenticationChecks.check(user); - DefaultPostAuthenticationChecks check expired credentials

It's good that preAuthenticationChecks and postAuthenticationChecks are links to the UserDetailsChecker interface, so you can change them. Just implement your own two UserDetailsChecker , one Null-Implementation for pre and one for the message, which checks everything:

  • !user.isAccountNonLocked()
  • !user.isEnabled()
  • !user.isAccountNonExpired()
  • !user.isCredentialsNonExpired()
+4
source

Source: https://habr.com/ru/post/1236996/


All Articles