Using Spring Security 4.0.2.RELEASE
对于使用spring-security框架的基本用户身份验证,我实现了spring-security DaoAuthenticationProvider
当用户尝试使用正确的用户名登录时,错误的密码和用户的帐户已经被锁定,那么我预计spring-security身份验证模块会抛出BadCredentialsException但是它会抛出LockedException
我的问题是
>为什么spring-security正在处理用户进行进一步的身份验证,而凭据特殊密码不正确?
>即使用户的密码无效,在应用程序中显示“用户已锁定”的消息是否良好?
>如何为无效密码和锁定用户设置生成/捕获BadCredentialsException?
任何帮助,将不胜感激.身份验证提供程序实现代码
@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 is thrown instead of BadCredentialsException,why?
这是因为Spring安全性将首先检查帐户是否存在且是否有效,然后检查密码.
更具体:它在AbstractUserDetailsAuthenticationProvider.authenticate中完成.在一个非常简短的描述中,方法以这种方式工作:
user = retrieveUser(username,(UsernamePasswordAuthenticationToken) authentication);
...
preAuthenticationChecks.check(user);
additionalAuthenticationChecks(user,(UsernamePasswordAuthenticationToken) authentication);
...
postAuthenticationChecks.check(user);
> retrieveUser – 加载用户
> preAuthenticationChecks.check(用户); – DefaultPreAuthenticationChecks:检查锁定…
> additionalAuthenticationChecks – 检查密码
> postAuthenticationChecks.check(user); – DefaultPostAuthenticationChecks检查未过期的凭据
好的一点是,preAuthenticationChecks和postAuthenticationChecks是对Interface UserDetailsChecker的引用,因此您可以更改它们.只需实现你自己的两个UserDetailsChecker,一个用于pre的Null-Implementation,一个用于检查所有内容的post:
>!user.isAccountNonLocked()
>!user.isEnabled()
>!user.isAccountNonExpired()
>!user.isCredentialsNonExpired()