本系列博文目錄:http://www.javashuo.com/article/p-ewndobct-kn.htmljava
登錄認證用於登陸時驗證登錄者的身份真實性。apache
咱們能夠經過 CA證書或用戶名密碼等方式進行認證。數組
shiro不會爲咱們提供現成的認證規則,須要咱們本身編寫認證規則。安全
編寫認證規則時咱們須要繼承AuthorizingRealm類,並實現doGetAuthenticationInfo抽象方法。app
public class ShiroRealm extends AuthorizingRealm { /** * 登陸認證(身份驗證) */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { /** * 本身實現的認證規則 */ } }
認證信息若是符合認證規則,則認證經過。ide
認證經過時須要返回一個認證信息接口AuthenticationInfo的實現類SimpleAuthenticationInfo 工具
/** * 登陸認證(身份驗證) */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { CaptchaAuthenticationToken authenticationToken = (CaptchaAuthenticationToken) token; //得到登陸令牌 String username = authenticationToken.getUsername(); String password = new String(authenticationToken.getPassword());//將char數組轉換成String類型 String captchaId = authenticationToken.getCaptchaId(); String captcha = authenticationToken.getCaptcha(); // 驗證用戶名密碼和驗證碼是否正確 usernamePasswordAndCaptchaAuthentication(username,password,captchaId,captcha); //建立身份信息類(自定義的) Principal principal = new Principal(1L, username); //認證經過返回認證信息類 return new SimpleAuthenticationInfo(principal, password, getName()); }
認證信息若是不符合認證規則,則認證不經過。url
認證不經過時拋出AuthenticationException異常或他的子類。spa
拋出異常後程序會進入到提交表單時指定的登陸方法,在這裏能夠經過.net
(String) request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME)
來得到異常類型,經過異常類型咱們就能夠判斷異常的緣由,從而進行提示或處理。
此方法只有在認證失敗後纔會訪問,認證成功後會直接訪問配置中指定的登錄成功路徑。
/** * LoginController中的登陸表單提交 * @param request * @param redirectAttributes * @return */ @RequestMapping(value = "/login", method = RequestMethod.POST) public String login(HttpServletRequest request, RedirectAttributes redirectAttributes) { //若是認證未經過得到異常並重定向到登陸頁 String message = null; String loginFailure = (String) request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);//取得登錄失敗異常 if (loginFailure.equals("pub.lichao.shiro.shiro.CaptchaAuthenticationException")) { message = "驗證碼錯誤";//自定義登錄認證異常 - 用於驗證碼錯誤提示 } else if (loginFailure.equals("org.apache.shiro.authc.UnknownAccountException")) { message = "用戶不存在";//未找到帳戶異常 }else if (loginFailure.equals("org.apache.shiro.authc.IncorrectCredentialsException")) { message = "密碼錯誤";//憑證(密碼)錯誤異常 } else if (loginFailure.equals("org.apache.shiro.authc.AuthenticationException")) { message = "帳號認證失敗";//認證異常 }else{ message = "未知認證錯誤";//未知認證錯誤 } //重定向參數傳遞,可以將參數傳遞到最終頁面 // (用addAttribute的時候參數會寫在url中因此要用addFlashAttribute) redirectAttributes.addFlashAttribute("message", message); return "redirect:login"; }
shiro默認的登錄失敗異常主要有如下這些
org.apache.shiro.authc.AuthenticationException //認證異常
|--org.apache.shiro.authc.AccountException //帳戶異常|--org.apache.shiro.authc.ConcurrentAccessException //單點登陸時帳戶多處登錄異常
|--org.apache.shiro.authc.DisabledAccountException //帳戶禁用異常
|--org.apache.shiro.authc.LockedAccountException //帳戶鎖定異常
|--org.apache.shiro.authc.ExcessiveAttemptsException //登錄錯誤次數超限異常
|--org.apache.shiro.authc.UnknownAccountException //未找到帳戶異常
|--org.apache.shiro.cas.CasAuthenticationException //CAS證書異常
|--org.apache.shiro.authc.CredentialsException //憑證(密碼)異常
|--org.apache.shiro.authc.ExpiredCredentialsException //憑證(密碼)過時異常
|--org.apache.shiro.authc.IncorrectCredentialsException //憑證(密碼)錯誤異常
|--org.apache.shiro.authc.pam.UnsupportedTokenException //令牌異常
若是這些異常沒法描述自定義規則中的某種錯誤,咱們能夠經過繼承AuthenticationException方式,編寫本身的認證異常。例如驗證碼錯誤異常
package pub.lichao.shiro.shiro; import org.apache.shiro.authc.AuthenticationException; /** * 自定義登錄認證異常 - 用於驗證碼錯誤提示 */ public class CaptchaAuthenticationException extends AuthenticationException { }
實現AuthorizingRealm類的doGetAuthorizationInfo方法,編寫本身的認證規則
/** * 登陸認證(身份驗證) */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { CaptchaAuthenticationToken authenticationToken = (CaptchaAuthenticationToken) token; //得到登陸令牌 String username = authenticationToken.getUsername(); String password = new String(authenticationToken.getPassword());//將char數組轉換成String類型 String captchaId = authenticationToken.getCaptchaId(); String captcha = authenticationToken.getCaptcha(); // 驗證用戶名密碼和驗證碼是否正確 usernamePasswordAndCaptchaAuthentication(username,password,captchaId,captcha); //建立身份信息類(自定義的) Principal principal = new Principal(1L, username); //認證經過返回認證信息類 return new SimpleAuthenticationInfo(principal, password, getName()); }
自定義的登陸認證異常
package pub.lichao.shiro.shiro; import org.apache.shiro.authc.AuthenticationException; /** * 自定義登錄認證異常 - 用於驗證碼錯誤提示 */ public class CaptchaAuthenticationException extends AuthenticationException { }
提交表單時指定的登陸方法
/** * LoginController中的登陸表單提交 * @param request * @param redirectAttributes * @return */ @RequestMapping(value = "/login", method = RequestMethod.POST) public String login(HttpServletRequest request, RedirectAttributes redirectAttributes) { //若是認證未經過得到異常並重定向到登陸頁 String message = null; String loginFailure = (String) request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);//取得登錄失敗異常 if (loginFailure.equals("pub.lichao.shiro.shiro.CaptchaAuthenticationException")) { message = "驗證碼錯誤";//自定義登錄認證異常 - 用於驗證碼錯誤提示 } else if (loginFailure.equals("org.apache.shiro.authc.UnknownAccountException")) { message = "用戶不存在";//未找到帳戶異常 }else if (loginFailure.equals("org.apache.shiro.authc.IncorrectCredentialsException")) { message = "密碼錯誤";//憑證(密碼)錯誤異常 } else if (loginFailure.equals("org.apache.shiro.authc.AuthenticationException")) { message = "帳號認證失敗";//認證異常 }else{ message = "未知認證錯誤";//未知認證錯誤 } //重定向參數傳遞,可以將參數傳遞到最終頁面 // (用addAttribute的時候參數會寫在url中因此要用addFlashAttribute) redirectAttributes.addFlashAttribute("message", message); return "redirect:login"; }
退出登陸時只要使用Subject的logout()方法便可。
/** * 退出登陸 * @param redirectAttributes * @return */ @RequestMapping(value = "/logout", method = RequestMethod.GET) public String logout(RedirectAttributes redirectAttributes) { //調用shiro管理工具類的退出登陸方法 SecurityUtils.getSubject().logout(); redirectAttributes.addFlashAttribute("message", "您已安全退出"); return "redirect:login"; //退出後返回到登陸頁 }