位运算和权限管理系统
简介
在 Linux 文件系统中用户对文件有 读
、写
、执行
三种权限,可以分别使用数字:4
、2
、1
三个数字来表示。三个数字任意组合可以表示不同的权限,例如: 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 // 读 + 写 + 执行
为什么是1
、2
、4
?1
、2
、4
的二进制表现形式是001
、010
、100
,它们的二进制表现形式只有一位是1
。这样,在权限叠加时,不会出现进位的情况。我们就可以判断最终结果的二进制位的0
、1
情况来判断是否有此权限。
例如读 + 写
权限 101
。第一位读
权限为1
,有读
权限。第二位写
权限为0
,无写权限。第三位执行
权限为1
表示有执行权限。
位运算实现权限操作
或运算实现权限的添加
增加权限使用或
(|
)运算实现。
如,为用户增加“读取”、“写入”两种权限1
2
3
4读 写 执行 二进制 十进制
0 1 0 ==> 010 ==> 2
1 0 0 ==> 100 ==> 4
1 1 0 ==> 110 ==> 6 // 或(|)运算结果
“读写”两种权限,权限码为6
(110
),其由权限码2
(010
)和4
(100
)进行或
(|
)运算后实现,即:6 = 2 | 4
,也可以由6 = 2 + 4
计算得出。
1 | addPermission (权限集值, 权限项) { |
与运算实现权限的判断
在需要进行用户权限判断时,可以使用与
(&
)运算判断用户是否据有某项权限。
如,判断权限码为6
用户是否有读取权限:1
2
3
4读 写 执行 二进制 十进制
1 1 0 ==> 110 ==> 6
1 0 0 ==> 100 ==> 4
1 0 0 ==> 100 ==> 4 // 与(&)运算结果
权限码6
(110
)和4
(100
)的与运算结果为 4
,即:4 = 6 & 4
。
判断权限码为6用户是否有执行权限:1
2
3
4读 写 执行 二进制 十进制
1 1 0 ==> 110 ==> 6
0 0 1 ==> 001 ==> 1
0 0 0 ==> 000 ==> 0 // 与(&)运算结果
权限码6
(110
)和1
(001
)的与运算结果为0
,即:0 = 6 & 1
。
根据与运算的计算规律,当运算结果为所要判断权限本身值时,我们可以认为用户具有这个权限。而当运算结果为 0
时,我们可以认为用户不具有这个权限。
1 | checkPermission (权限集值, 权限项) { |
非运算实现权限的减少
位运算同样可以实现用户权限的减少,减少用户权限使用非
(^
)运算。
如,将权限码为7
用户,移除执行权限:1
2
3
4读 写 执行 二进制 十进制
1 1 1 ==> 110 ==> 7
0 0 1 ==> 001 ==> 1
1 1 0 ==> 000 ==> 6 // 非(^)运算结果
权限码7
(111
)和1
(001
)的非运算结果为6
,即:6 = 7 ^ 1
,也可以由6 = 7 - 1
计算得出。
1 | deletePermission (权限集值, 权限项) { |
延伸
如果权限集超过三种呢?
例子:用位权限表示增
、删
、改
、查
。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)。