1. 程式人生 > >Spring Boot +Shiro 驗證碼Filter和限制密碼錯誤次數

Spring Boot +Shiro 驗證碼Filter和限制密碼錯誤次數

驗證碼校驗

CustomFormAuthenticationFilter 將我們自己實現的Filter,放到ShiroFilterFactoryBean中。

 ShiroFilterFactoryBean shiroFilterFactoryBean  = new ShiroFilterFactoryBean();
        Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();//獲取filters
        filters.put("authc", new CustomFormAuthenticationFilter());//將自定義 的FormAuthenticationFilter注入shiroFilter中

CustomFormAuthenticationFilter.java

public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        // 在這裡進行驗證碼的校驗
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpSession session = httpServletRequest.getSession();

        // 取出驗證碼
String validateCode = (String) session.getAttribute("validateCode"); // 取出頁面的驗證碼 // 輸入的驗證和session中的驗證進行對比 String randomcode = httpServletRequest.getParameter("randomcode"); if (randomcode != null && validateCode != null && !randomcode.equals(validateCode)) { // 如果校驗失敗,將驗證碼錯誤失敗資訊,通過shiroLoginFailure設定到request中
httpServletRequest.setAttribute("shiroLoginFailure", "kaptchaValidateFailed");//自定義登入異常 // 拒絕訪問,不再校驗賬號和密碼 return true; } return super.onAccessDenied(request, response); } }

密碼錯誤次數限制登入

RetryLimitHashedCredentialsMatcher 繼承HashedCredentialsMatcher
在我們實現的MyShiroRealm密碼匹配器中使用我們自己寫的RetryLimitHashedCredentialsMatcher
重點內容

 /**
     * 身份認證realm;
     * (這個需要自己寫,賬號密碼校驗;許可權等)
     * @return
     */
    @Bean
    public MyShiroRealm myShiroRealm(){
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());;
        return myShiroRealm;
    }
    /**
     * 憑證匹配器
     * (由於我們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了
     *  所以我們需要修改下doGetAuthenticationInfo中的程式碼;
     * )
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
//        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        HashedCredentialsMatcher hashedCredentialsMatcher = new RetryLimitHashedCredentialsMatcher(ehCacheManager());
        hashedCredentialsMatcher.setHashAlgorithmName("md5");//雜湊演算法:這裡使用MD5演算法;
        hashedCredentialsMatcher.setHashIterations(2);//雜湊的次數,比如雜湊兩次,相當於 md5(md5(""));
        return hashedCredentialsMatcher;
    }
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
    private Cache<String, AtomicInteger> passwordRetryCache;

    public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
        passwordRetryCache = cacheManager.getCache("passwordRetryCache");
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token,
                                      AuthenticationInfo info) {
        String username = (String) token.getPrincipal();
        // retry count + 1
        AtomicInteger retryCount = passwordRetryCache.get(username);
        if (retryCount == null) {
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(username, retryCount);
        }
        if (retryCount.incrementAndGet() > 5) {
            // if retry count > 5 throw
            throw new ExcessiveAttemptsException();
        }

        boolean matches = super.doCredentialsMatch(token, info);
        if (matches) {
            // clear retry count
            passwordRetryCache.remove(username);
        }
        return matches;
    }

}