Shiro 实现 RememberMe 功能

本文内容:Shiro 中RememberMe 功能的介绍以及实现。

1

介绍

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

基本流程如下:

1、首先在登录页面选中RememberMe然后登录成功;如果是浏览器登录,一般会把RememberMe的Cookie写到客户端并保存下来;

2、关闭浏览器再重新打开;会发现浏览器还是记住你的;

3、访问一般的网页服务器端还是知道你是谁,且能正常访问;

4、但是比如我们访问淘宝时,如果要查看我的订单或进行支付时,此时还是需要再进行身份认证的,以确保当前用户还是你。

关于拦截器

访问一般网页,如个人在主页之类的,我们使用user拦截器即可,user拦截器只要用户登录(isRemembered()==true||isAuthenticated()==true)通过即可访问成功;

访问特殊网页,如我的订单,提交订单页面,我们使用authc拦截器,authc拦截器会判断用户是否是通过

Subject.login(isAuthenticated()==true)

登录的,如果是才放行,否则会跳转到登录页面叫你重新登录。

关于rememberMecookie

shiro自动对用户对象序列化并加密. 当获得请求时, 能够获取反序列化且解密之后的用户对象。

当设置rememberMe==false, 将会自动清空rememberMe cookie.

不想要自动登录怎么办?

调用shirologout()方法, 即消除自动登录功能。

2

实现

ShiroConfig.java 中添加配置

注意:

cookieRememberMeManager.setCipherKey

传入参数为长度16位的byte[],否则会报Unable to init cipher instance:无法初始化密码实例的错误。

/**     * cookie对象;     * @return     */    public SimpleCookie rememberMeCookie(){        //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");        //cookie生效时间30天,单位秒;        simpleCookie.setMaxAge(2592000);        return simpleCookie;    }
    /**     * cookie管理对象;记住我功能     * @return     */    public CookieRememberMeManager rememberMeManager(){        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();        cookieRememberMeManager.setCookie(rememberMeCookie());        cookieRememberMeManager.setCipherKey("ZHANGXIAOHEI_CAT".getBytes());        return cookieRememberMeManager;    }

注入到SecurityManager

@Bean(name="securityManager")  public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();    //关联realm    securityManager.setRealm(userRealm);    //使用记住我    securityManager.setRememberMeManager(rememberMeManager());    return securityManager;  }

修改登录页面login.html

用戶:
密碼:
记住我

修改LoginController.java

@RequestMapping(value="/login",method = RequestMethod.GET)  public String toLogin(Model model) {    Subject subject = SecurityUtils.getSubject();      System.out.println(subject.isRemembered());    System.out.println(subject.isAuthenticated());    if(subject.isRemembered()){      System.out.println("-------------------------------------------------");            System.out.println("认证成功");            DzmHisMember member = (DzmHisMember)subject.getPrincipal();            model.addAttribute("member",member);            return "redirect:/toHome";        }    return "login";  }
  @RequestMapping(value="/login",method = RequestMethod.POST)  public String login(String userName,String password,boolean rememberMe,Model model)  {    /**     * 使用Shiro编写认证操作     *///1.获取Subject    Subject subject = SecurityUtils.getSubject();  //2.封装用户数据    UsernamePasswordToken token = new UsernamePasswordToken(userName,password);//3.执行登录方法    try {      System.out.println(rememberMe);      token.setRememberMe(rememberMe);      subject.login(token);      //登录成功,跳转到主页面      return "redirect:/toHome";    } catch (UnknownAccountException e) {      //登录失败:用户名不存在      model.addAttribute("msg", "用户名不存在");      return "login";    }catch (IncorrectCredentialsException e) {      //登录失败:密码错误      model.addAttribute("msg", "密码错误");      return "login";    }  }
  • 前一次登录勾选了记住我, 则本次登录时isRemembered()==true(如果上一次设置了rememberme, 本次登录是不会触发action中的login()的方法的, 即会直接进入登录状态)。

  • 经过shirologin()则表示为认证登录的. 就是说authentication==true. 访问权限最高.

  • rememberMe==true, 则将不会进入任何action. 可以访问所有user控制的页面或路径. 但不能访问authc控制的面或路径。

 这里有个关键点:

subject.isAuthenticated()==true,则 subject.isRemembered()==false;

反之同理。

3

测试

在地址栏输入http://localhost:8080/hospital/login,第一次登陆时勾选“记住我”,登陆成功后关闭该页面;再在地址栏输入

http://localhost:8080/hospital/login会直接进入主页而不是登陆页面,控制台输出如下:

至此,本文结束。欢迎各位关注我的公众号:暗星涌动。

Shiro 实现 RememberMe 功能_第1张图片

你可能感兴趣的:(SpringBoot)