Spring Boot系列(十五) 安全框架Apache Shiro(三)RememberMe

Shiro提供了记住我(RememberMe)的功能,比如访问如淘宝等一些网站时,关闭了浏览器下次再打开时还是能记住你是谁,下次访问时无需再登录即可访问,基本流程如下:

  1. 首先在登录页面选中RememberMe然后登录成功;如果是浏览器登录,一般会把RememberMe的Cookie写到客户端并保存下来;
  2. 关闭浏览器再重新打开;会发现浏览器还是记住你的;
  3. 访问一般的网页服务器端还是知道你是谁,且能正常访问;
  4. 但是比如我们访问淘宝时,如果要查看我的订单或进行支付时,此时还是需要再进行身份认证的,以确保当前用户还是你。

下面是基于上一章节缓存的案例,增加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 或 / 页面时,会允许访问。
Spring Boot系列(十五) 安全框架Apache Shiro(三)RememberMe_第1张图片

你可能感兴趣的:(SpringBoot,Shiro,RememberMe)