Shiro提供了记住我(RememberMe)的功能,比如访问如淘宝等一些网站时,关闭了浏览器下次再打开时还是能记住你是谁,下次访问时无需再登录即可访问,基本流程如下:
下面是基于上一章节缓存的案例,增加RememberMe的步骤:
步骤1:在ShiroConfiguration配置中 创建Cookie(记住我)管理器@Bean
/**
* cookie管理器;
* @return
*/
@Bean
public CookieRememberMeManager rememberMeManager(){
logger.info("注入Shiro的记住我(CookieRememberMeManager)管理器-->rememberMeManager", CookieRememberMeManager.class);
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
//rememberme cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位),通过以下代码可以获取
//KeyGenerator keygen = KeyGenerator.getInstance("AES");
//SecretKey deskey = keygen.generateKey();
//System.out.println(Base64.encodeToString(deskey.getEncoded()));
byte[] cipherKey = Base64.decode("wGiHplamyXlVB11UXWol8g==");
cookieRememberMeManager.setCipherKey(cipherKey);
cookieRememberMeManager.setCookie(rememberMeCookie());
return cookieRememberMeManager;
}
@Bean
public SimpleCookie rememberMeCookie(){
//这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
//如果httyOnly设置为true,则客户端不会暴露给客户端脚本代码,使用HttpOnly cookie有助于减少某些类型的跨站点脚本攻击;
simpleCookie.setHttpOnly(true);
//记住我cookie生效时间,默认30天 ,单位秒:60 * 60 * 24 * 30
simpleCookie.setMaxAge(259200);
return simpleCookie;
}
步骤2:将Cookie管理器注入到SecurityManager中
@Bean
public SecurityManager securityManager() {
logger.info("注入Shiro的Web过滤器-->securityManager", ShiroFilterFactoryBean.class);
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//设置Realm,用于获取认证凭证
securityManager.setRealm(userRealm());
//注入缓存管理器
securityManager.setCacheManager(ehCacheManager());
//注入Cookie(记住我)管理器(remenberMeManager)
securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
步骤3:当访问指定路径资源时,只需要记录我就能访问,则在ShiroFilterFactoryBean添加记住我过滤器:user
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
...
Map filterChainDefinitionMap = new LinkedHashMap();
// 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout");
//配置记住我过滤器或认证通过可以访问的地址(当上次登录时,记住我以后,在下次访问/或/index时,可以直接访问,不需要登陆)
filterChainDefinitionMap.put("/index", "user");
filterChainDefinitionMap.put("/", "user");
//过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
...
return shiroFilterFactoryBean;
}
步骤4:目前我们采用的是创建Token的方式来登陆:UsernamePasswordToken(用户名,密码,是否记住我),在创建Token后,加上token.setRememberMe(true),修改SecurityController;
例如:
if(request.getParameter("rememberMe")!=null){
token.setRememberMe(true);
}
@RequestMapping(value="/login",method=RequestMethod.POST)
public String login(HttpServletRequest request, @Valid User user,BindingResult bindingResult,RedirectAttributes redirectAttributes){
...
UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), user.getPassword());
if(request.getParameter("rememberMe")!=null){
token.setRememberMe(true);
}
//获取当前的Subject
Subject currentUser = SecurityUtils.getSubject();
...
}
如果是采用FormAuthenticationFilter来认证的话,如果勾上了记住我,会自动帮我们设置上true。
步骤5: 修改login.html
...
<br />
<div class="checkbox">
<label>
<input id="rememberMe" name="rememberMe" type="checkbox" /> Remember me
label>
div>
<br />
<button type="submit" style="width:280px;" class="btn btn-default">登 录button>
...
步骤6:测试
当第一次打开浏览器访问 /index 或 / 时,自动跳转到登陆页面,勾选 Remember Me登陆时,如果浏览器关闭(当前session亦失效),重新打开浏览器访问 /index 或 / 页面时,会允许访问。