package com.shi.shiro; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; import org.springframework.http.HttpRequest; /** * 自定義的驗證碼校驗過濾器 繼承FormAuthenticationFilter * @author SHF * 問題: 之後全部的都要進行驗證碼校驗 (這個要解決) * */ public class CustomFormAuthenticationFilter extends FormAuthenticationFilter{ //覆蓋FormAuthenticationFilter 認證的方法 @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { //1 先進行驗證碼的校驗 //從session中獲取正確的驗證碼 HttpServletRequest httpRequest=(HttpServletRequest)request; /*HttpSession session=httpRequest.getSession(); //從session中取出正確的 驗證碼信息 String validateCode=(String) session.getAttribute("validateCode");*/ //模擬從session中取出正確的驗證碼 String validateCode="abc"; //取出頁面輸入的驗證碼 String realmCode=httpRequest.getParameter("realmCode"); System.out.println("頁面輸入的驗證碼是:"+realmCode); if(validateCode!=null && realmCode!=null && !validateCode.equals(realmCode)){ //2 驗證碼認證失敗 講驗證碼錯誤信息保存到request中的 shiroLoginFailure 屬性中 httpRequest.setAttribute("shiroLoginFailure", "realmErr"); //拒絕訪問 ,不在驗證帳號和密碼 return true; } //3 驗證碼認證成功 就進行用戶名和密碼的認證 return super.onAccessDenied(request, response); } }
2 配置自定義CustomFormAuthenticationFilterjava
<!-- 7.1 自定義form認證過濾器 --> <bean id="formAuthenticationFilter" class="com.shi.shiro.CustomFormAuthenticationFilter"> <!-- 表單帳號中 input名稱 --> <property name="usernameParam" value="username"></property> <!-- 表單中密碼的input名稱 --> <property name="passwordParam" value="password"></property> </bean> <!-- 1 配置filter對應的bean --> <!-- shiro的web過濾器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 1.1 配置安全管理器 --> <property name="securityManager" ref="securityManager"/> <!-- 1.2 loginUrl認證提交地址,若是沒有認證將會請求此地址進行認證,請求此地址將由formAuthenticationFilter進行表單認證--> <property name="loginUrl" value="/login.action" /> <!-- 1.3 unauthorizedUrl指定沒有權限時跳轉頁面--> <property name="unauthorizedUrl" value="/refuse.action" /> <!-- 1.5 配置成功頁面 --> <property name="successUrl" value="/first.action"/> <!-- 7.2 把自定義的filter配置到 過濾器鏈中 --> <property name="filters"> <map> <!-- 講自定義的CustomFormAuthenticationFilter 注入到shiroFilter中 --> <entry key="authc" value-ref="formAuthenticationFilter"></entry> </map> </property> <!-- 1.4 過濾器鏈的定義 --> <property name="filterChainDefinitions"> <value> <!-- 對靜態資源進行匿名訪問 --> /images/**=anon <!-- 請求logout.action地址,shiro去清空session --> /logout.action=logout <!-- /**=authc 表示全部url都必須認證經過以後開能夠訪問 --> <!-- 受權的控制 下面經過註解的方式開啓受權--> <!-- /items/query.action=perms[items:query] /user/query.action=perms[user:query] --> <!-- 對全部剩下的認證 --> /**=authc <!-- /**=anon anon全部的url均可以匿名訪問 --> <!-- /**=anon --> </value> </property> </bean>
3 在login.action對驗證錯誤 進行解析web
//登陸提交地址,和applicationContext-shiro.xml文件 中配置的loginUrl保持一致 @RequestMapping("/login") public String Login(HttpServletRequest request) throws Exception{ //若是失敗從request中獲取認證異常信息,shiroLoginFilure就是shiro異常類的權限類名 /*String exceptionClassName=request.getParameter("shiroLoginFailure");*/ String exceptionClassName=(String) request.getAttribute("shiroLoginFailure"); System.out.println("登陸異常=========="+exceptionClassName); //根據shiro返回的異常類路徑判斷,拋出指定異常信息 if(exceptionClassName!=null){ if(UnknownAccountException.class.getName().equals(exceptionClassName)){ throw new CustomException("帳戶不存在"); }else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)){ System.out.println("密碼錯誤"); throw new CustomException("用戶名/密碼錯誤"); }else if("realmErr".equals(exceptionClassName)){ throw new CustomException("驗證碼錯誤"); }else{ throw new Exception();//最終在異常處理器生成未知異常 } }
4 在登錄頁面添加驗證碼spring
5 在filter配置匿名訪問驗證碼jspapache