跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

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)

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

关于

rememberMe

cookie shiro

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

当设置

rememberMe==false

, 将会自动清空rememberMe cookie.

不想要自动登录怎么办? 调用

shiro

logout()

方法, 即消除自动登录功能。

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()

的方法的, 即会直接进入登录状态)。

经过

shiro

login()

则表示为认证登录的. 就是说

authentication==true

. 访问权限最高.

rememberMe==true

, 则将不会进入任何action. 可以访问所有

user

控制的页面或路径. 但不能访问

authc

控制的面或路径。

这里有个关键点: subject.isAuthenticated()==true,则 subject.isRemembered()==false; 反之同理。

3 测试 在地址栏输入http://localhost:8080/hospital/login,第一次登陆时勾选“记住我”,登陆成功后关闭该页面;再在地址栏输入 http://localhost:8080/hospital/login会直接进入主页而不是登陆页面,控制台输出如下:

至此,本文结束。

欢迎各位关注我的公众号:暗星涌动。

相关文章