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登录页面,当登录成功后,关闭浏览器重新打开再输入地址后,不需要重新登录,直接跳转。

posted @ 2019-01-11 17:14  华丽D转身  阅读(3508)  评论(0编辑  收藏  举报