Spring Security:抛出LockedException而不是BadCredentialsException,为什么?

使用Spring Security 4.0.2.RELEASE

对于使用spring-security框架的基本用户身份validation,我实现了spring-security DaoAuthenticationProvider

当用户尝试使用正确的用户名登录时, 错误的密码和用户的帐户已被锁定 ,那么我预计spring-security身份validation模块将抛出BadCredentialsException但是它会抛出LockedException

我的问题是

  1. 为什么spring-security正在处理用户进行进一步的身份validation,而凭据特殊密码不正确?
  2. 即使用户的密码无效,在应用程序中显示“用户已锁定”的消息是否良好?
  3. 如何为无效密码和锁定用户设置生成/捕获BadCredentialsException

任何帮助,将不胜感激。 身份validation提供程序实现代码

 @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; } } } 

你问:

Spring Security:抛出LockedException而不是BadCredentialsException,为什么?

这是因为Spring安全性将首先检查帐户是否存在且是否有效,然后检查密码。

更具体:它在AbstractUserDetailsAuthenticationProvider.authenticate完成。 在一个非常简短的描述中,方法以这种方式工作:

 user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); ... preAuthenticationChecks.check(user); additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); ... postAuthenticationChecks.check(user); 
  • retrieveUser – 加载用户
  • preAuthenticationChecks.check(user);DefaultPreAuthenticationChecks :检查锁定…
  • additionalAuthenticationChecks – 检查密码
  • postAuthenticationChecks.check(user);DefaultPostAuthenticationChecks检查未过期的凭据

好的一点是, preAuthenticationCheckspostAuthenticationChecks是对Interface UserDetailsChecker引用,因此您可以更改它们。 只需实现自己的两个UserDetailsChecker ,一个用于pre的Null-Implementation,一个用于检查所有内容的post:

  • !user.isAccountNonLocked()
  • !user.isEnabled()
  • !user.isAccountNonExpired()
  • !user.isCredentialsNonExpired()