位运算和权限管理系统

简介

在 Linux 文件系统中用户对文件有 执行三种权限,可以分别使用数字:421 三个数字来表示。三个数字任意组合可以表示不同的权限,例如: 7 (4 + 2 + 1)表示用户对对此文件拥有所有权限,6 (4 + 2)表示用户对此文件有权限。

为什么是1、2、4 ?

对于 执行 我们用0表示由此权限,1表示无此权限。

1
2
3
4
5
6
7
8
9
10
读 写 执行        二进制     十进制
0 0 0 ==> 000 ==> 0
0 0 1 ==> 001 ==> 1 // 执行
0 1 0 ==> 010 ==> 2 // 写
1 0 0 ==> 100 ==> 4 // 读

0 1 1 ==> 011 ==> 3 // 执行 + 写
1 0 1 ==> 101 ==> 5 // 读 + 执行
1 1 0 ==> 110 ==> 6 // 读 + 写
1 1 1 ==> 111 ==> 7 // 读 + 写 + 执行

为什么是124?
124 的二进制表现形式是001010100,它们的二进制表现形式只有一位是1。这样,在权限叠加时,不会出现进位的情况。我们就可以判断最终结果的二进制位的01情况来判断是否有此权限。
例如读 + 写 权限 101。第一位权限为1,有权限。第二位权限为0,无写权限。第三位执行权限为1表示有执行权限。

位运算实现权限操作

或运算实现权限的添加

增加权限使用|)运算实现。

如,为用户增加“读取”、“写入”两种权限

1
2
3
4
读   写   执行      二进制     十进制
0 1 0 ==> 010 ==> 2
1 0 0 ==> 100 ==> 4
1 1 0 ==> 110 ==> 6 // 或(|)运算结果

“读写”两种权限,权限码为6110),其由权限码2010)和4100)进行|)运算后实现,即:6 = 2 | 4,也可以由6 = 2 + 4计算得出。

1
2
3
addPermission (权限集值, 权限项) {
return 权限集值 | 权限项
}

与运算实现权限的判断

在需要进行用户权限判断时,可以使用&)运算判断用户是否据有某项权限。

如,判断权限码为6用户是否有读取权限:

1
2
3
4
读   写   执行      二进制     十进制
1 1 0 ==> 110 ==> 6
1 0 0 ==> 100 ==> 4
1 0 0 ==> 100 ==> 4 // 与(&)运算结果

权限码6110)和4100)的与运算结果为 4,即:4 = 6 & 4

判断权限码为6用户是否有执行权限:

1
2
3
4
读   写   执行      二进制      十进制
1 1 0 ==> 110 ==> 6
0 0 1 ==> 001 ==> 1
0 0 0 ==> 000 ==> 0 // 与(&)运算结果

权限码6110)和1001)的与运算结果为0,即:0 = 6 & 1

根据与运算的计算规律,当运算结果为所要判断权限本身值时,我们可以认为用户具有这个权限。而当运算结果为 0 时,我们可以认为用户不具有这个权限。

1
2
3
checkPermission (权限集值, 权限项) {
return 权限集值 & 权限项 == 权限项
}

非运算实现权限的减少

位运算同样可以实现用户权限的减少,减少用户权限使用^)运算。

如,将权限码为7用户,移除执行权限:

1
2
3
4
读   写   执行      二进制      十进制
1 1 1 ==> 110 ==> 7
0 0 1 ==> 001 ==> 1
1 1 0 ==> 000 ==> 6 // 非(^)运算结果

权限码7111)和1001)的非运算结果为6,即:6 = 7 ^ 1,也可以由6 = 7 - 1计算得出。

1
2
3
deletePermission (权限集值, 权限项) {
return 权限集值 ^ 权限项
}

延伸

如果权限集超过三种呢?
例子:用位权限表示

1
2
3
4
5
6
7
8
9
10
11
增 删 改  查        二进制     十进制
0 0 0 0 ==> 0000 ==> 0
0 0 0 1 ==> 0001 ==> 1 // 查
0 0 1 0 ==> 0010 ==> 2 // 改
0 1 0 0 ==> 0100 ==> 4 // 删
1 0 0 0 ==> 1000 ==> 8 // 增

0 0 1 1 ==> 0011 ==> 3 // 改 + 查
0 1 1 1 ==> 0111 ==> 7 // 删 + 改 + 查
1 1 1 1 ==> 1111 ==> 15 // 增 + 删 + 改 + 查
1 0 1 1 ==> 1011 ==> 11 // 增 + 改 + 查

如果类型有N种,我们就用N位二进制来表示。

位运算也有一些局限性,随着权限码增加,数据长度也相应的增长。这就要求权限码不能超过计算本身运算长度,在数据库中存储权限码时,权限码长度也不能的超过所使用数据类型。如:在32位系统中不能超过232,也就是权限数量不能多于32个。而mySQL数据库的BIGINT,其存储空间为8Byte,使用BIGINT存储存储码时,权限数不能多于64个(8*8-1)。

参考

【1】 【2】 【3】

本站采用「署名 4.0 国际」进行许可。