在登錄的時候,咱們通常都設置有驗證碼,可是咱們若是使用Shiro的話,那麼Shiro默認的是使用FormAuthenticationFilter進行表單認證。javascript
而咱們的驗證校驗的功能應該加在FormAuthenticationFilter中,在認證以前進行驗證碼校驗。css
FormAuthenticationFilter是Shiro默認的功能,咱們想要在FormAuthenticationFilter以前進行驗證碼校驗,就須要繼承FormAuthenticationFilter類,改寫它的認證方法!java
public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {
//原FormAuthenticationFilter的認證方法
@Override
protected boolean onAccessDenied(ServletRequest request,
ServletResponse response) throws Exception {
//在這裏進行驗證碼的校驗
//從session獲取正確驗證碼
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpSession session =httpServletRequest.getSession();
//取出session的驗證碼(正確的驗證碼)
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", "randomCodeError");
//拒絕訪問,再也不校驗帳號和密碼
return true;
}
return super.onAccessDenied(request, response);
}
}
咱們編寫完自定義類之後,是須要在Shiro配置文件中配置咱們這個自定義類的。web
因爲這是咱們自定義的,所以咱們並不須要用戶名就使用username,密碼就使用password,這個也是咱們能夠自定義的。apache
<!-- 自定義form認證過慮器 -->
<!-- 基於Form表單的身份驗證過濾器,不配置將也會註冊此過慮器,表單中的用戶帳號、密碼及loginurl將採用默認值,建議配置 -->
<bean id="formAuthenticationFilter" class="cn.itcast.ssm.shiro.CustomFormAuthenticationFilter ">
<!-- 表單中帳號的input名稱 -->
<property name="usernameParam" value="username" />
<!-- 表單中密碼的input名稱 -->
<property name="passwordParam" value="password" />
</bean>
在Shiro的bean中注入自定義的過濾器安全
<!-- 自定義filter配置 --> <property name="filters"> <map> <!-- 將自定義 的FormAuthenticationFilter注入shiroFilter中--> <entry key="authc" value-ref="formAuthenticationFilter" /> </map> </property>
在咱們的Controller添加驗證碼錯誤的異常判斷,從咱們的Controller就能夠發現,爲何咱們要把錯誤信息存放在request域對象shiroLoginFailure,由於咱們得在Controller中獲取獲取信息,從而給用戶對應的提示markdown
@RequestMapping("login") public String login(HttpServletRequest request)throws Exception{ //若是登錄失敗從request中獲取認證異常信息,shiroLoginFailure就是shiro異常類的全限定名 String exceptionClassName = (String) request.getAttribute("shiroLoginFailure"); //根據shiro返回的異常類路徑判斷,拋出指定異常信息 if(exceptionClassName!=null){ if (UnknownAccountException.class.getName().equals(exceptionClassName)) { //最終會拋給異常處理器 throw new CustomException("帳號不存在"); } else if (IncorrectCredentialsException.class.getName().equals( exceptionClassName)) { throw new CustomException("用戶名/密碼錯誤"); } else if("randomCodeError".equals(exceptionClassName)){ throw new CustomException("驗證碼錯誤 "); }else { throw new Exception();//最終在異常處理器生成未知錯誤 } } //此方法不處理登錄成功(認證成功),shiro認證成功會自動跳轉到上一個請求路徑 //登錄失敗還到login頁面 return "login"; }
<TR>
<TD>驗證碼:</TD>
<TD><input id="randomcode" name="randomcode" size="8" /> <img id="randomcode_img" src="${baseurl}validatecode.jsp" alt="" width="56" height="20" align='absMiddle' /> <a href=javascript:randomcode_refresh()>刷新</a></TD>
</TR>
Shiro還提供了記住用戶名和密碼的功能!cookie
用戶登錄選擇「自動登錄」本次登錄成功會向cookie寫身份信息,下次登錄從cookie中取出身份信息實現自動登錄。session
想要實現這個功能,咱們的認證信息須要實現Serializable接口。app
public class ActiveUser implements java.io.Serializable { private String userid;//用戶id(主鍵) private String usercode;// 用戶帳號 private String username;// 用戶名稱 private List<SysPermission> menus;// 菜單 private List<SysPermission> permissions;// 權限 }
<!-- rememberMeManager管理器,寫cookie,取出cookie生成用戶信息 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cookie" ref="rememberMeCookie" />
</bean>
<!-- 記住我cookie -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!-- rememberMe是cookie的名字 -->
<constructor-arg value="rememberMe" />
<!-- 記住我cookie生效時間30天 -->
<property name="maxAge" value="2592000" />
</bean>
注入到安全管理器類上
<!-- securityManager安全管理器 --> <bean id="securityManager"~~~···· <property name="cacheManager" ref="cacheManager"/> <!-- 注入session管理器 --> <property name="sessionManager" ref="sessionManager" /> <!-- 記住我 --> <property name="rememberMeManager" ref="rememberMeManager"/> </bean>
配置頁面的input名稱:
<tr>
<TD></TD>
<td><input type="checkbox" name="rememberMe" />自動登錄</td>
</tr>
若是設置了「記住我」,那麼訪問某些URL的時候,咱們就不須要登錄了。將記住我便可訪問的地址配置讓UserFilter攔截。
<!-- 配置記住我或認證經過能夠訪問的地址 -->
/index.jsp = user
/first.action = user
/welcome.jsp = user