【问题标题】:Spring Security : LockedException is thrown instead of BadCredentialsException, why?Spring Security:抛出 LockedException 而不是 BadCredentialsException,为什么?
【发布时间】:2016-03-02 09:27:27
【问题描述】:

使用 Spring Security 4.0.2.RELEASE

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

当用户尝试使用正确的用户名、不正确的密码和用户的帐户已被锁定登录时,我预计 spring-security 身份验证模块会抛出 BadCredentialsException但它会抛出 LockedException

我的问题是

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

任何帮助将不胜感激。 Authentication Provider 实现代码是

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

}

【问题讨论】:

    标签: java spring spring-security


    【解决方案1】:

    你问:

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

    这是因为spring security会先检查账号是否存在且有效,然后再检查密码。

    更具体:在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 是对接口 UserDetailsChecker 的引用,因此您可以更改它们。只需实现您自己的两个UserDetailsChecker,一个用于 pre 的 Null-Implementation 和一个用于检查所有内容的 post:

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

    【讨论】:

    • 那是我不知道的关于 spring-security 的事情。还有一件事,在实际情况下,如果我们告诉用户帐户被锁定,即使密码错误,谁正在尝试进行身份验证? ???
    • @Waseem Akhtar:我无法证明您的第二个问题是正确的:“这是一种好的做法……”,但恕我直言,您是对的。 -- 无论如何,Spring(安全)的好处是,您只需要查看代码即可回答像您这样的问题,至少我是这样做的。
    • 也可以在这里查看这个答案stackoverflow.com/a/56202422/1533783
    猜你喜欢
    • 2017-07-11
    • 1970-01-01
    • 2022-10-04
    • 2012-05-19
    • 2015-11-12
    • 2015-07-29
    • 2014-12-24
    • 2019-08-03
    • 1970-01-01
    相关资源
    最近更新 更多