shiro实现基于机构加用户名的验证以及rememberMe

一、Shiro的一些经验与rememberMe实现原理

Shiro的登录(Authorization)和验权(Authentication),默认都是根据用户名UserName来做验证和授权的。

登录用的是UsernamePasswordToken用户名密码对,验权用的是PrincipalCollection身份集合(默认是用户名和Realm名称),有一个统一的入口就是Subject(表示一个人或其他什么的要登录进来的对象)。

关系是登陆时subject.login(token),然后登陆成功了subject里就有了subject.getPrincipal(),拿到此用户的用户名了。

任何地方都可以直接使用工具方法拿到subject: Subject subject = SecurityUtils.getSubject();

可以通过subject.isAuthenticated()为true可以判断当前用户已经登录过了;此时可以直接通过subject.getSession()去获取我们放入session的信息了。

如果subject.isRemembered()为true,则登录后,Shiro会将principal对象序列化为Byte[],再base64,添加到客户端的cookie里,默认过期时间为1年。用户下次访问登录时,直接将cookie里的rememberMe数据拿出来,传到服务器端,Shiro即可反序列化,还原出来原用户的身份信息。在浏览器的设置里可以查看这个base64的cookie值:


二、实现机构加用户名的验证

Shiro默认这一套机制都是按照用户名来做的。现在我们的系统里存在多个机构,不同机构可以有相同的用户名,那么我们怎么来实现基于机构+用户名的验证呢?

两个思路可以解决这个问题:

  1. 把机构+用户名拼接到一起来作为UsernamePasswordToken里的UserName
  2. 扩展UsernamePasswordToken与Principal的实现

这两个思路各有利弊,第一个比较简单粗暴,第二个比较规范通用。

由于我们是先做好基于UserName的实现以后再修改代码实现把机构扩展进去,所以第一种方式改动最小:

  1. 系统登录页面表单加上机构类型与机构名称选择,
  2. 后台把机构类型+机构id+username拼接成admin:1:3的形式,作为UsernamePasswordToken的Username,
  3. Realm实现使用自定义的或者我写的这个ServiceRealm(只有3个类)SQL改成根据机构id+username获取密码
  4. 然后使用subject.login登录即可实现基于机构+用户的验证。
  5. 登录后查看subject.getPrincipal已经是admin:1:3的形式了。

第二种以后再分析。

三、如上修改UserName格式+rememberMe造成的一个小问题

如果浏览器之前使用了rememberMe选型以后安装上面的方式修改了UserName格式(比如admin:1:3),则因为其cookie有效期为1年,每次再自动登录诗、从客户端提交上来的序列化的cookie数据里都是旧的数据,还原出来的principal还是老的格式(比如admin),造成了数据不一致,程序执行出错。

解决办法:清空浏览器的cookie,或者直接强制客户端使用一次login登录即可。


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kimmking

赠人玫瑰手有余香

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值