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

