1. 程式人生 > >SpringBoot學習:整合shiro自動登入功能(rememberMe記住我功能)

SpringBoot學習:整合shiro自動登入功能(rememberMe記住我功能)

首先在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登入頁面,當登入成功後,關閉瀏覽器重新開啟再輸入地址後,不需要重新登入,直接跳轉。