shiro实现基于机构加username的验证以及rememberMe

本文介绍了Shiro框架中登录及权限验证的工作原理,并详细解释了rememberMe功能的实现过程。此外,还探讨了如何针对多机构场景进行扩展,以支持基于机构+用户名的验证方式。文中提及了在修改用户名格式后rememberMe功能可能遇到的问题及其解决方案。

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

Shiro的登录(Authorization)和验权(Authentication)。默认都是依据usernameUserName来做验证和授权的。

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

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

不论什么地方都能够直接使用工具方法拿到subject: Subject subject = SecurityUtils.getSubject();

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

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


二、实现机构加username的验证

Shiro默认这一套机制都是依照username来做的。如今我们的系统里存在多个机构,不同机构能够有同样的username,那么我们怎么来实现基于机构+username的验证呢?

两个思路能够解决问题:

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

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

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

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

另外一种以后再分析。

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

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

解决的方法:清空浏览器的cookie,或者直接强制client使用一次login登录就可以。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值