场景描述
系统分为管理端和客户端,管理端具有对客户端某个资源的访问权限的管理功能。
项目主要涉及技术Springboot+Vue+Shiro
原始代码
UserReal.java
下的doGetAuthorizationInfo()
方法最开始是这样的:
// 进入设置了拦截的页面就会触发这个方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Subject subject = SecurityUtils.getSubject();
// 这里开始赋权
// 严格来说这里应该从数据库取出权限数据再赋权,这里为了简便省略
info.addStringPermission("poweraaa");
info.addStringPermission("powerbbb");
return info;
}
需求描述
传统需求 | 目标需求 |
---|---|
简单的权限管理,但是存在一个问题:管理员端发送请求修改数据库后,客户端再去访问设置了权限拦截的请求的时候,由于原来的代码只是简单的addStringPermission ,即增加权限,所以在管理员修改权限的情况下,客户在Shiro中对应的那一个会话并没有删除某个权限 | 管理员修改数据库后,客户端能够马上感知到修改结果,即得到没有权限的提示或者在没有权限的基础上能够访问某个资源了 |
传统方式的解决方式
根据对传统需求的分析,管理员修改了客户的某个权限后,客户只有重新退出Shiro,即:
Subject currentUser = SecurityUtils.getSubject();
currentUser.logout();
才能保证在下一次用户登陆的时候,重新去数据库拿到权限数据,再重新赋权
目标需求思路探究
既然解决问题的根本是权限集在每一次doGetAuthorizationInfo
执行的时候都得到最新的数据库权限数据,而不是在原有的权限集的基础上增加,那么在每一次执行这个函数的最开始,将权限集清空,再去数据库拿数据,那么每一次拿到的数据就是最新的了,而且是在空权限集的基础上的赋权,不会存在之前的权限还在的问题。
代码如下:
// 进入设置了拦截的页面就会触发这个方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Subject subject = SecurityUtils.getSubject();
// 关键代码-------------------------------------------------------
Set<String> set = new HashSet<>(); // 定义一个空的集合
info.setStringPermissions(set); // 手动设置当前用户的权限为一个空的集合,相当于清空了用户权限
// 关键代码-------------------------------------------------------
// 这里开始赋权
// 严格来说这里应该从数据库取出权限数据再赋权,这里为了简便省略
info.addStringPermission("poweraaa");
info.addStringPermission("powerbbb");
return info;
}