1,谈
最近在开发系统的权限模块,之前一直没有接触过,只有活学活用了。一般系统的权限:
①功能权限
应用场景:一个系统中有A,B菜单,A,B页面,页面各有增,删,改,查 ,功能按钮,路人甲(角色)被赋予 查看A页面,及拥有A页面的增加按钮功能,当路人甲登录系统时,他就只能看到A菜单,A页面,及A页面下的一个增加按钮。
对于功能权限,采用的设计当然是成熟的RBAC。由于这块相关资料网上流传较多,在本文中不再展开。
②数据权限
应用场景:当路人甲(角色)被赋予不同的数据权限时,登录时就会展示不同的数据。
x,能详细点不?一般来说,一个公司的系统中,数据必定有其所属者,这些数据或通过职位或通过创建者而确定其所归属。通常,自己的数据自己能查看,而不能查看他人的数据,或者职位高的管理者是天然的可以看到其所在部门及所有下属的数据的。
但若是想让职位低的员工也能跨职位跨部门查看到某些数据呢?这就需要将这些数据的权限赋予给某些角色或角色组(角色组看各自需求决定去留),这些员工通过角色关联便可实现对这些本不能查看的数据的查看。
2,设计
到底怎么搞呢,表结构是怎样的,实现的过程是怎样的。
在系统中,我是称这种权限为“共享规则”,这是基于每个业务对象,通过把对象中某部门某职位(或及下属)的数据共享给某个角色,当某用户拥有这个角色,那么他也就查看这个对象中自己本来能查看的数据(也即是自己及下属的数据)+共享给角色的数据。
这一切在代码中是通过拼接 mysql 子句来实现的,在设置这种共享规则时,①基于数据本身的归属也就是根据这些数据属于哪个职位的用户拥有的,生成子句时就是:and positionId in(xxx) ,这里的xxx根据设置时选择的是职位或职位及其下属,若是后者,则先通过positionId 找出其所有下属positionId,将这些positionId全部放进xxx中。②基于对象的字段条件,也就是根据表中一些字段为条件。生成子句时就是:and xxx > 200 and xxx = aa 。然后保存在表中,性能方面的优化,我采用的方案是将这张表放在内存数据库中。
3,实现
表:(rule)
id resource(业务对象名称) roleId(角色ID) scope(mysql 子句)
基本代码:(注意rule与role)
List<Role> roles = getRole(userId);
List<Rule> rules = new ArrayList<>();
String resource="xx";//业务对象名称
for(Role r : roles){
rules.all(getRule(resource,roleId));
}
//当rules.size()>1时,则后面的需要使用 or 来放大数据范围。
//在sql中,当然这里可能会涉及多表的查询,处理+sub 时可能会复杂一些。
select * from xxx where 1=1 + sub
简单的版本过程基本就是这样。