Linux二进制权限在前端中的应用
需求
修改权限模块,逻辑方面倒是没花太多时间,加上画新的ui一天就差不多搞定了,可是我看到一个这么一个东西
(record.permission & PERMISSION_ACTION[type]) > 0 // 代码经过简化
我知道这是位与运算符,不知道的请 => MDN详解: 表达式与运算符 - JavaScript | MDN
但是从来没有在实践中使用过这个东西。花了点时间研究了一下,发现这是Linux的二进制权限,接下来展开说下实际应用
首先把权限的权重分为五个档位,用数字表示就是1,2,4,8,16
问题1:为啥不分成1、2、3、4、5呢?
解答:好问题,我一开始也是这么想的,反正对于我来说,每个档位有一个唯一值类似id的东西就可以进行判断了,想到这里膜拜一波Linux的智慧,不过这也是我的知识盲区(我是从平面转到前端的。
我们现在有五个档位的权限,查看、创建、编辑、删除、下载,分别对应档位1、2、4、8、16。
每后面一个的权限都包含前面所有的权限,比如有创建权限,那肯定有查看权限吧,有编辑权限,那就也有查看和创建权限,以此类推。
权限变动后我们发给后端的数据不是['查看'、'创建'、'编辑'、'删除'、'下载']这种被选中的值的数组,而是权限的权重和(1、3、7、15、31),我选中的是编辑,那我的权限值就是7。
- 1 => 查看 1 = 1
- 3 => 查看\创建 1+2 = 3
- 7 => 查看\创建\编辑 1+2+4 = 7
- 15 => 查看\创建\编辑\删除 1+2+4+8 = 15
- 31 => 查看\创建\编辑\删除\下载 1+2+4+8+16 = 31
| 十进制 | 二进制 | 次幂 |
|---|---|---|
| 1 | 000001 | 2^0 |
| 3 | 000011 | 2^2-1 |
| 4 | 000100 | 2^2 |
| 7 | 001111 | 2^3-1 |
| 8 | 001000 | 2^3 |
| 15 | 011111 | 2^4-1 |
| 16 | 010000 | 2^4 |
| 31 | 011111 | 2^5-1 |
| 32 | 100000 | 2^5 |
问题1 总结
3、7、15、31分别包含之前所有的权限,我们在二进制的角度下会发现他们都是2的次幂减1
这个时候通过我上面说到的逻辑与运算符,就可以判断权限的包含关系
例子:
3&1 //1
3&2 //2
7&1 //1
7&2 //2
7&4 //4
7&16 //0
// 大于0就是包含前置权限,等于0就是不包含
......
这样通过权重和就可以去进行前置权限的判断
问题2:如何通过后端返的权限值()获取选中的权限?Switch吗?
不,Switch太麻烦也不易维护,我们有比它更好的办法
&运算符(位与),简述:两个二进制上下比较,都为1才是1
// 定义各权限的键值对
const PERMISSION_ACTION = {
VIEW: 1 << 0,
ADD: 1 << 1,
MODIFY: 1 << 2,
DELETE: 1 << 3,
DOWNLOAD: 1 << 4
};
// 通过权限和获取对应的权限
const getPermissionTypes = (permission: number)=>{
return ['VIEW','ADD','MODIFY','DELETE','DOWNLOAD'].filter((type)=>{
if(permission & PERMISSION_ACTION[type]) return type;
})
}
在控制台跑了一下,没问题,getPermissionTypes函数就能帮我们获取到权限值相对应的权限
问题3:如何通过选中的权限名字获得其权限值及其前置权限的和?
我选中了删除权限,那么我的权限值应该是1+2+4+8 = 15,对吧
这里我们用 | 运算符(位或), 简述:两个二进制比较,有一个为1就是1
以下是实现
// 权限类型
const PERMISSION_TYPE = [
// 预览权限
'VIEW',
// 新增权限
'ADD',
// 修改权限
'MODIFY',
// 删除权限
'DELETE',
// 下载权限
'DOWNLOAD'
];
// 定义各权限的键值对
const PERMISSION_ACTION = {
VIEW: 1 << 0,
ADD: 1 << 1,
MODIFY: 1 << 2,
DELETE: 1 << 3,
DOWNLOAD: 1 << 4
};
// 通过选中的权限获取其与所有前置权限
const getPerssionNum = (permissions: PermissionType[]) => {
let res: number = 0;
permissions.forEach((key) => {
res = res | PERMISSION_ACTION[key];
});
return res;
};
想了解更多,百度 Linux二进制权限
以上就是全部,有问题反馈