shiro學習筆記(6)--spring整合及可能遇到的問題小結
阿新 • • 發佈:2018-11-14
上篇spring整合shiro後續…
spring整合shiro主要是org.apache.shiro.web.filter.authc.FormAuthenticationFilter類。
1、controller
@Controller public class HelloSsm { @RequestMapping(value = {"/","tologin.do"}) public String tologin(){ return "models/sys/login"; } @RequestMapping("login.do") public String login(Model model, User user, HttpServletRequest request){ //進入login.do說明shiro認證失敗 /** * 在FormAuthenticationFilter中,將認證失敗的異常類資訊儲存在request的shiroLoginFailur中 */ String className = (String) request.getAttribute("shiroLoginFailure"); if(UnknownAccountException.class.getName().equals(className)){ System.out.println("賬號有誤!"); }else if(DisabledAccountException.class.getName().equals(className)){ System.out.println("禁用的賬號!"); }else if(ExcessiveAttemptsException.class.getName().equals(className)){ System.out.println("登入次數過多!"); }else if(ConcurrentAccessException.class.getName().equals(className)){ System.out.println("併發訪問異常!"); }else if(IncorrectCredentialsException.class.getName().equals(className)){ System.out.println("密碼錯誤!"); }else if(ExpiredCredentialsException.class.getName().equals(className)){ System.out.println("密碼過期!"); }else { System.out.println("系統錯誤"); } String message = "賬號或密碼錯誤,請重試..."; request.setAttribute("message",message); return "models/sys/login"; } @RequestMapping("index.do") public String index(Model model,HttpServletRequest request){ User user = (User) SecurityUtils.getSubject().getPrincipal(); if(user!=null) { request.setAttribute("username", user.getUsername()); } return "models/sys/index"; } }
2、login.jsp
注意:form提交表單需要post方式,否則FormAuthenticationFilter將無法進入自定義realm中的認證方法。
<form action="login.do" style="background-color: burlywood" method="post"> username:<input type="text" name="username"><br/> password:<input type="password" name="password"><br/> <c:if test="${message!=null && message!=''}"> <input type="text" value="${message}" style="font-weight: bold;font-size:10px;"> </c:if> <input type="submit" value="login"> </form>
3、跑起來,你可能會碰到的坑~
(1)無法進入realm的認證方法
查看錶單提交方式是否是post
(2)無法注入service
這個問題曾困擾了好久,原因有很多。
首先是web容器中filter載入優先於servlet,為此在filter中無法使用spring註解,需要將spring載入優先順序設定更高(當然也可能無效)
其次:仍然無效時需要通過工具類獲取spring上下文,以獲取需要注入的service
loginService = SpringBeanFactoryUtils.getBean(LoginService.class);
@Component public class SpringBeanFactoryUtils implements ApplicationContextAware{ private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (SpringBeanFactoryUtils.applicationContext == null) { SpringBeanFactoryUtils.applicationContext = applicationContext; } } public static ApplicationContext getApplicationContext() { return applicationContext; } //根據名稱(@Resource 註解) public static Object getBean(String name) { return getApplicationContext().getBean(name); } //根據型別(@Autowired) public static <T> T getBean(Class<T> clazz) { return getApplicationContext().getBean(clazz); } public static <T> T getBean(String name, Class<T> clazz) { return getApplicationContext().getBean(name, clazz); } }
(3)loginUrl和successUrl及filterChainDefinitions配置
注意路徑設定與認證不要衝突
(4)認證失敗
首先是確保是否獲取了完整的使用者資訊。在realm的認證入參AuthenticationToken中檢視
其次是斷點跟蹤認證是否正常
(5)認證完成跳轉路徑
認證後跳轉路徑是根據shiro的xml配置確定的,個人建議最好設定successUrl。這樣當認證失敗時可完整記錄失敗異常資訊
說一下認證失敗時資訊獲取:
/**
* 在FormAuthenticationFilter中,將認證失敗的異常類資訊儲存在request的shiroLoginFailur中
*/
String className = (String) request.getAttribute("shiroLoginFailure");