在权限设计中有一种非常独特且有意思方案叫位掩码权限设计,它在应对一些局部数据权限(权限点不多)的场景下,非常的犀利,比如 PingCode 知识管理页面权限就结合 ACL 对特定人群(用户、用户组、部门)做权限分配,最近做的一个低代码项目中的某块业务也表现很突出,多次尝到甜头分享给大家
什么是位掩码权限?
维基百科搜了一下没有正式对位掩码权限的解释,还得是 ChatGPT:
位掩码权限(Bitmask Permissions)是一种权限管理系统,用于在计算机系统中对资源或操作进行控制和限制。它使用二进制位来表示不同的权限或访问级别。每个二进制位都代表一种权限或操作,可以设置为开启或关闭。
了解过 Linux 权限的应该知道它的一些权限点:r(read 读)、w(write 写)、x(execute 执行),对应的权限值是 4、2、1。
这是一个标准的位掩码权限设计,其中 1、2、4 对应着基于“位”的二进制,拿 4 位举例: 1 => 0001
, 2 => 0010
, 4 => 0100
。
几个名词的小知识:
mask 掩码,常表示权限,Worktile 中出现过 x 的全称是 execute,之所以用这个字母表示,起源于 Unix 的设计哲学...... 简单的字母 x 更简洁、可读性高,表示最小单元,最基本的操作。后续业界很多也采用这种方式,我说一种大家就知道了 Lodash 使用回调函数第一个参数 _.map(arr, x=> x.name);
常见权限处理
1. 赋予多种权限
采用累计权限点的方式,比如拥有“读”+“写”,4 + 2 = 6,那么最终权限值是 6,拥有“读”+“写”+“执行”,那权限值是:4 + 2 + 1 = 7,以此类推,根据场景搭配权限点即可。
2. 判断是否拥有某种权限
使用位运算 & ,比如现已拥有的权限值是 3,想知道是否有可见(读)权限,那么就执行 !!(3 & 2) 结果是 true , 3 & 2 结果是 2,& 的思路是把 10 进制转换成 2 进制比较,二进制”与“的规则是同为 1 则为 1,否则为 0,和 2 的指数相与,结果必定只有两种结果:0 或 本身,把二进制的计算结果再转回 10 进制,0 代表无权限,权限点代表有此权限,更具体的二进制计算可以点这里。
判断只拥有一种权限,全等比较即可,比如只读(除读之外没有其他权限)inputPermission === 4
,如果权限值是列表或字符串的情况还需要做排他处理,很是麻烦。
3. 页面展示权限点
页面如何展示这些权限点以及映射也是值得思考的问题,不过在这种权限模式下就比较灵活了,因为权限值是一个数字而非数组或字符串,数组和字符串前后端是必须都要映射索引的,必然会有一套计算权限的逻辑,对于数字来说,是一个无序的,前端配置静态固定位置,映射方式就使用上述的与运算一行代码即可。
优缺点
总的来说,位掩码在局部权限设计的场景下比较突出(权限点少且相互之间依赖性低):
但是它不适合权限点多,粒度细的系统,位就不够用了(第 10 个权限点已经是 1024 了)
实际应用
需求界面是这样的:
对应填写表单是这样的:
选型
选用哪门技术/手段,必然要考虑各种因素(业务场景、已有架构、易用、质量、性能),这里简单介绍一些前置条件:
针对于上述条件可以得出的结论就是本文讲的 位掩码权限的设计方案, 其实中间环节是可以有很多思考的(不感兴趣的可以跳过) 一些结论:
选用位掩码权限的方式有这些优势:
permissions: {
read: true,
write: true,
require: true
}
// good
permissions: 7
最后
还是重复两点吧:
最后提供可以直接使用的代码片段: