簡體   English   中英

Spring 安全性:拋出 LockedException 而不是 BadCredentialsException,為什么?

[英]Spring Security : LockedException is thrown instead of BadCredentialsException, why?

使用 Spring 安全 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;
        }
    }

}

您詢問:

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()

當有多個用戶在數據庫中具有相同的憑據(名稱,email 等)時,我得到了這個異常。 無論如何這是一個測試。 在我刪除這些重復項后,一切正常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM