SpringBoot学习:整合shiro(rememberMe记住我功能)
在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登录页面,当登录成功后,关闭浏览器重新打开再输入地址后,不需要重新登录,直接跳转。