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

  • 相关阅读:
    OCM_Session1_2_Server-side Network Configuration
    sql union代替or
    创建组合索引SQL从1个多小时到1S的案例
    OCM_session0手动建库实验
    慎用位图索引
    Java之List排序
    Java之List排序出错
    dojo、iframe和FusionCharts兼容性
    Java之indexOf()方法
    Java之split()方法
  • 原文地址:https://www.cnblogs.com/snake23/p/10256207.html
Copyright © 2020-2023  润新知