原理
使用FormAuthenticationFilter過慮器實現 ,原理如下:
將用戶沒有認證時,請求loginurl進行認證,用戶身份和用戶密碼提交數據到loginurl
FormAuthenticationFilter攔截住取出request中的username和password(兩個參數名稱是可以配置的)
FormAuthenticationFilter調用realm傳入一個token(username和password)
realm認證時根據username查詢用戶信息(在Activeuser中存儲,包括 userid、usercode、username、menus)。
如果查詢不到,realm返回null,FormAuthenticationFilter向request域中填充一個參數(記錄了異常信息)
登陸頁面
由於FormAuthenticationFilter的用戶身份和密碼的input的默認值(username和password),修改頁面的賬號和密碼 的input的名稱爲username和password
代碼控制:(只對錯誤進行控制,認證過程由realm傳遞給Authenticator認證信息)
package cn.qlq.springmvc.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import cn.qlq.springmvc.Exception.MyException; import cn.qlq.springmvc.pojo.ActiveUser; import cn.qlq.springmvc.service.SysService; @Controller public class LoginController { @Autowired private SysService sysService; // 登陸提交地址,和applicationContext-shiro.xml中配置的loginurl一致 @RequestMapping("/login.action") 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 MyException("賬號不存在"); } else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) { throw new MyException("用戶名/密碼錯誤"); } else if ("randomCodeError".equals(exceptionClassName)) { throw new MyException("驗證碼錯誤 "); } else { throw new Exception("不是賬戶錯誤,也不是密碼錯誤");// 最終在異常處理器生成未知錯誤 } } // 此方法不處理登陸成功(認證成功),shiro認證成功會自動跳轉到上一個請求路徑 // 登陸失敗還到login頁面 return "login"; } }
認證過濾攔截器
--------------------------------------------退出-------------------------------
使用LogoutFilter
不用我們去實現退出,只要去訪問一個退出的url(該 url是可以不存在),由LogoutFilter攔截住,清除session。
在applicationContext-shiro.xml配置LogoutFilter: