shiro學習筆記 過濾器 shiro 表單 驗證碼 登入
阿新 • • 發佈:2019-02-20
自己自定義實現了一個驗證碼錶單過濾器,基於FormAuthenticationFilter
程式碼如下:
package cn.ddsxy.ddlx.shiro; import cn.ddsxy.ddlx.util.CaptchaUtil; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.subject.Subject; import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; import org.apache.shiro.web.util.WebUtils; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * 自定義表單過濾器 * @author zhiguang */ public class CaptchaFormAuthentcationFileter extends FormAuthenticationFilter { /** * 是否開啟驗證碼支援 */ private boolean captchaEbabled = true; /** * 驗證碼引數名 */ private String captchaParam = "captcha"; public boolean isCaptchaEbabled() { return captchaEbabled; } public void setCaptchaEbabled(boolean captchaEbabled) { this.captchaEbabled = captchaEbabled; } public String getCaptchaParam() { return captchaParam; } public void setCaptchaParam(String captchaParam) { this.captchaParam = captchaParam; } public String getCaptcha(ServletRequest request){ return WebUtils.getCleanParam(request, this.getCaptchaParam()); } @Override protected CaptchaUserNamePassWordToken createToken(ServletRequest request, ServletResponse response) { String username = request.getParameter("username"); String password = request.getParameter("password"); String captcha = request.getParameter("captcha"); return new CaptchaUserNamePassWordToken(username, password==null?"":password, captcha); } @Override protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { CaptchaUserNamePassWordToken token = createToken(request, response); try { if(captchaEbabled) CaptchaUtil.verify(request); Subject subject = getSubject(request, response); subject.login(token); return onLoginSuccess(token, subject, request, response); } catch (IncorrectCaptchaException e) { return onLoginFailure(token, e, request, response); } catch (UnknownAccountException e1) { // 不存在使用者名稱對應的有效使用者記錄 return onLoginFailure(token, e1, request, response); } catch (IncorrectCredentialsException e2) { // 使用者名稱或密碼不對 return onLoginFailure(token, e2, request, response); } catch (AuthenticationException e3) { // 其它異常 return onLoginFailure(token, e3, request, response); } } @Override protected void setFailureAttribute(ServletRequest request, AuthenticationException e) { if(e instanceof IncorrectCaptchaException){ request.setAttribute(DEFAULT_ERROR_KEY_ATTRIBUTE_NAME,"驗證碼錯誤"); }else if(e instanceof UnknownAccountException){ request.setAttribute(DEFAULT_ERROR_KEY_ATTRIBUTE_NAME,"使用者不存在"); }else if(e instanceof IncorrectCredentialsException){ request.setAttribute(DEFAULT_ERROR_KEY_ATTRIBUTE_NAME,"密碼錯誤"); }else if(e instanceof AuthenticationException){ request.setAttribute(DEFAULT_ERROR_KEY_ATTRIBUTE_NAME,"登入失敗"); } } /** * 表示訪問拒絕時是否自己處理,如果返回true表示自己不處理且繼續攔截器鏈執行,返回false表示自己已經處理了(比如重定向到另一個頁面) * @param request * @param response * @return * @throws Exception */ @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { return super.onAccessDenied(request, response); } /** * 是否允許訪問,返回true表示允許 * @param request * @param response * @param mappedValue * @return */ @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { return super.isAccessAllowed(request, response, mappedValue); } }
CaptchaUtil.verify該方法驗證驗證碼是否正確,可自行實現,重要的是executeLogin這個方法,我開始瞭解shiro的時候一直分不清這個FormAuthenticationFilter過濾器和Realm的doGetAuthenticationInfo(身份認證)有什麼關係,看原始碼,看到了AuthenticatingFilter這個父類executeLogin方法裡呼叫了
我明白了,這個過濾器無非還是用subject進行登入,shiro實現登入就這個介面protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { AuthenticationToken token = this.createToken(request, response); if (token == null) { String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken must be created in order to execute a login attempt."; throw new IllegalStateException(msg); } else { try { Subject subject = this.getSubject(request, response); subject.login(token); return this.onLoginSuccess(token, subject, request, response); } catch (AuthenticationException var5) { return this.onLoginFailure(token, var5, request, response); } } }