在shiro配置類中注入rememberMe管理器:
1 /** 2 * cookie對象; 3 * rememberMeCookie()方法是設置Cookie的生成模版,比如cookie的name,cookie的有效時間等等。 4 * @return 5 */ 6 @Bean 7 public SimpleCookie rememberMeCookie(){ 8 //System.out.println("ShiroConfiguration.rememberMeCookie()"); 9 //這個參數是cookie的名稱,對應前端的checkbox的name = rememberMe 10 SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); 11 //<!-- 記住我cookie生效時間30天 ,單位秒;--> 12 simpleCookie.setMaxAge(259200); 13 return simpleCookie; 14 } 15 16 /** 17 * cookie管理對象; 18 * rememberMeManager()方法是生成rememberMe管理器,而且要將這個rememberMe管理器設置到securityManager中 19 * @return 20 */ 21 @Bean 22 public CookieRememberMeManager rememberMeManager(){ 23 //System.out.println("ShiroConfiguration.rememberMeManager()"); 24 CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); 25 cookieRememberMeManager.setCookie(rememberMeCookie()); 26 //rememberMe cookie加密的密鑰 建議每個項目都不一樣 默認AES算法 密鑰長度(128 256 512 位) 27 cookieRememberMeManager.setCipherKey(Base64.decode("2AvVhdsgUs0FSA3SDFAdag==")); 28 return cookieRememberMeManager; 29 } 30 31 @Bean(name = "securityManager") 32 public DefaultWebSecurityManager defaultWebSecurityManager(MyShiroRealm realm){ 33 DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 34 //設置realm 35 securityManager.setRealm(realm); 36 //用戶授權/認證信息Cache, 采用EhCache緩存 37 securityManager.setCacheManager(getEhCacheManager()); 38 //注入記住我管理器 39 securityManager.setRememberMeManager(rememberMeManager()); 40 return securityManager; 41 }
配置記住我或認證通過可以訪問的地址:
1 /** 2 * 加載ShiroFilter權限控制規則 3 */ 4 private void loadShiroFilterChain(ShiroFilterFactoryBean factoryBean) { 5 /**下面這些規則配置最好配置到配置文件中*/ 6 Map<String, String> filterChainMap = new LinkedHashMap<String, String>(); 7 //配置記住我或認證通過可以訪問的地址 8 filterChainMap.put("/", "user"); 9 /** authc:該過濾器下的頁面必須驗證后才能訪問,它是Shiro內置的一個攔截器 10 * org.apache.shiro.web.filter.authc.FormAuthenticationFilter */ 11 // anon:它對應的過濾器里面是空的,什么都沒做,可以理解為不攔截 12 //authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問 13 filterChainMap.put("/permission/userInsert", "anon"); 14 filterChainMap.put("/error", "anon"); 15 filterChainMap.put("/tUser/insert","anon"); 16 filterChainMap.put("/**", "authc"); 17 18 factoryBean.setFilterChainDefinitionMap(filterChainMap); 19 }
登錄jsp,並設置記住我的選項:
1 <body style="margin-left: 500px"> 2 <h1 style="margin-left: 30px">登錄頁面----</h1> 3 <form action="<%=basePath%>/login" method="post"> 4 用戶名 : <input type="text" name="email" id="email"/><br> 5 密碼: <input type="password" name="pswd" id="pswd"/><br> 6 驗證碼:<input type="text" name="gifCode" id="gifCode"/> 7 <img alt="驗證碼" src="<%=basePath%>gif/getGifCode"><br> 8 <input type="checkbox" name="rememberMe" />記住我<br> 9 <input style="margin-left: 100px" type="submit" value="登錄"/><input style="left: 50px" onclick="register()" type="button" value="注冊"/> 10 </form> 11 <h1 style="color: red">${message }</h1> 12 </body>
后台的登錄處理方法參數用boolean類型接收,並且在得到身份驗證Token時傳入rememberMe參數:
1 @RequestMapping(value="/login",method=RequestMethod.POST) 2 public String login(@Valid User user, BindingResult bindingResult,boolean rememberMe, 3 RedirectAttributes redirectAttributes){ 4 if(bindingResult.hasErrors()){ 5 return "redirect:login"; 6 } 7 String email = user.getEmail(); 8 if(StringUtils.isBlank(user.getEmail()) || StringUtils.isBlank(user.getPswd())){ 9 logger.info("用戶名或密碼為空! "); 10 redirectAttributes.addFlashAttribute("message", "用戶名或密碼為空!"); 11 return "redirect:login"; 12 } 13 //對密碼進行加密后驗證 14 UsernamePasswordToken token = new UsernamePasswordToken(user.getEmail(), 15 CommonUtils.encrypt(user.getPswd()),rememberMe); 16 //獲取當前的Subject 17 Subject currentUser = SecurityUtils.getSubject(); 18 try { 19 //在調用了login方法后,SecurityManager會收到AuthenticationToken,並將其發送給已配置的Realm執行必須的認證檢查 20 //每個Realm都能在必要時對提交的AuthenticationTokens作出反應 21 //所以這一步在調用login(token)方法時,它會走到MyRealm.doGetAuthenticationInfo()方法中,具體驗證方式詳見此方法 22 logger.info("對用戶[" + email + "]進行登錄驗證..驗證開始"); 23 currentUser.login(token); 24 logger.info("對用戶[" + email + "]進行登錄驗證..驗證通過"); 25 }catch(UnknownAccountException uae){ 26 logger.info("對用戶[" + email + "]進行登錄驗證..驗證未通過,未知賬戶"); 27 redirectAttributes.addFlashAttribute("message", "未知賬戶"); 28 }catch(IncorrectCredentialsException ice){ 29 logger.info("對用戶[" + email + "]進行登錄驗證..驗證未通過,錯誤的憑證"); 30 redirectAttributes.addFlashAttribute("message", "密碼不正確"); 31 }catch(LockedAccountException lae){ 32 logger.info("對用戶[" + email + "]進行登錄驗證..驗證未通過,賬戶已鎖定"); 33 redirectAttributes.addFlashAttribute("message", "賬戶已鎖定"); 34 }catch(ExcessiveAttemptsException eae){ 35 logger.info("對用戶[" + email + "]進行登錄驗證..驗證未通過,錯誤次數大於5次,賬戶已鎖定"); 36 redirectAttributes.addFlashAttribute("message", "用戶名或密碼錯誤次數大於5次,賬戶已鎖定"); 37 }catch (DisabledAccountException sae){ 38 logger.info("對用戶[" + email + "]進行登錄驗證..驗證未通過,帳號已經禁止登錄"); 39 redirectAttributes.addFlashAttribute("message", "帳號已經禁止登錄"); 40 }catch(AuthenticationException ae){ 41 //通過處理Shiro的運行時AuthenticationException就可以控制用戶登錄失敗或密碼錯誤時的情景 42 logger.info("對用戶[" + email + "]進行登錄驗證..驗證未通過,堆棧軌跡如下"); 43 ae.printStackTrace(); 44 redirectAttributes.addFlashAttribute("message", "用戶名或密碼不正確"); 45 } 46 //驗證是否登錄成功 47 if(currentUser.isAuthenticated()){ 48 logger.info("用戶[" + email + "]登錄認證通過(這里可以進行一些認證通過后的一些系統參數初始化操作)"); 49 //把當前用戶放入session 50 Session session = currentUser.getSession(); 51 User tUser = permissionService.findByUserEmail(email); 52 session.setAttribute("currentUser",tUser); 53 return "/welcome"; 54 }else{ 55 token.clear(); 56 return "redirect:login"; 57 } 58 }
啟動項目后,第一次進入頁面跳轉到login登錄頁面,當登錄成功后,關閉瀏覽器重新打開再輸入地址后,不需要重新登錄,直接跳轉。