根据权限查询时避免角色切换的一种思路

1. 问题背景

权限系统现状

UC权限系统基于角色访问控制技术RBAC(Role Based Access Control) 。具体来说,就是赋予用户某个角色,角色给与角色对应的权限能访问及操作不同范围的资源。

什么是数据权限

代表一个角色对应某个权限所能操作的数据范围,比如gitlab组管理员能看到组下的所有项目代码,我们可以这样配置:

  1. 创建组管理员
  2. 分配给组管理员查看项目代码的权限
  3. 查看项目代码权限设置约束条件,约束为自己组下的项目

实际产生遇到的问题

对绝大多数简单的系统来说一个用户对应一个系统只会有一个角色,一个角色只有一个数据权限范围(即使有多个,也可以合并成一个)。但是随着产品的功能迭代,用户的变更和系统设计的原因,总有一些特殊且重要的用户在同一个系统中拥有多个角色。在多角色和数据权限的组合下,一个用户可以拥有复数的数据权限范围。

考虑到实现复杂性,大多数系统选择使用角色切换的手段简化系统实现,同时对用户暴露出了他们不熟悉的角色这一概念,造成这些用户在系统使用中的各种不便。

本文重点讨论在避免角色切换的前提下,进行多角色数据范围查询的一种思路。

具体需要解决的需求

我们的数据报表后台,不同的角色拥有不同的数据查看范围(不同角色所能看到的员工数据字段也各不相同),例如:

  • 薪酬管理员:查看非高职级员工数据
  • 高级薪酬管理员: 查看高职级员工数据
  • 长期激励管理员:查看有长期激励员工数据
  • 等等

简单来说,拥有长期激励管理员和高级薪酬管理员的用户能否直接看到高职级员工数据和长期激励员工数据?至少在直觉上是可行的。

2.多角色数据范围查询

直觉的做法

单角色单数据范围可以使用一句sql查询出结果,那多角色多数据范围是不是使用多句sql查询出结果合并就可以了?

深入思考 多角色数据范围对行的影响

  1. 查询条件合并还是结果合并? —-结果合并
  2. 如何排序? —–外部排序,或先内部排序,limit,再外部排序
  3. 有重复数据怎么办? —-使用groupby去重
  4. 查询性能有影响吗?—-有

具体体现:

1
2
3
4
5
6
7
select * from (
(select id, sortvalue from table_1 where t_name = 'a' order by sortvalue desc limit 20) -- 先内部排序,limit
union all -- 结果合并
(select id, sortvalue from table_1 where t_name = 'b' order by sortvalue desc limit 20) -- 先内部排序,limit
order by sortvalue desc -- 外部排序
) a group by id -- 使用groupby去重
limit 10, 10

深入思考 多角色数据范围对列的影响

  • 薪酬管理员: 查看员工薪酬字段
  • 长期激励管理员:查看员工长期激励字段

如何解决?方法有很多!

综合思考,给出一种解决方案

1
2
3
graph LR
A(查询行及角色信息) --> B(根据角色查询对应列字段)
B --> C(结果)

步骤:

  1. 查询多角色数据范围下的数据,附带角色信息
1
2
3
4
5
6
7
select id, GROUP_CONCAT(a.role) as roles from (
(select id, 'role_a' as role from table_1 where sortvalue > 10 order by `sortvalue` desc limit 2)
union all
(select id, 'role_b' as role from table_1 where sortvalue > 20 order by `sortvalue` desc limit 2)
order by `sortvalue` desc
) a group by id
limit 0, 2

结果:

id roles
1 薪酬管理员
5 薪酬管理员,长期激励管理员
  1. 根据每一行不同的角色,查询出可见的字段,例如id=1的行只能查看ROLE_B对应字段,而id=5的行可以看到ROLE_A,ROLE_B对应的两个角色的字段

3.总结和延伸

多角色数据范围写操作?

遍历角色直到找到满足条件的权限即可。

收获

自己不行动,等于等着被别人安排哈哈

还有疑问?

自己想。还可以点这里