soarli

基于位运算进行权限管理设计
前言温神(CaprYang)在请假系统的开发中的对于用户权限的管理都是基于二进制掩码实现的,当时了解到此处时正在准...
扫描右侧二维码阅读全文
11
2022/01

基于位运算进行权限管理设计

前言

温神(CaprYang)在请假系统的开发中的对于用户权限的管理都是基于二进制掩码实现的,当时了解到此处时正在准备研考就没有过于深入的研究,近期对二进制位运算操作的基础知识加以巩固并于本文对其在实际应用中的权限控制场景加以系统性总结。

位运算

image-20220111030322191

参与运算的如果是10进制数,则会被转换至2进制数参与运算,然后计算结果会再转换为10进制数输出。

2^0=1,相应2进数为"0001"(这里^表示"次方",即:2的0次方,下同)
2^1=2,相应2进数为"0010"
2^2=4,相应2进数为"0100"
2^3=8,相应2进数为"1000"

image-20220111024313124

优点

位运算的运算对象是二进制的位,速度快,效率高,而且节省存储空间,位运算做权限控制又相当地灵活。Linux系统的文件权限的实现方式,就是采用了位运算

缺点

位运算也有很大的局限,因为在32位计算机上,位移不能超过32次,这就要求权限数量不超过32种。

示例1

<?php
define("PUBLIC_ARTICLE",  1);    //发行文章
define("CREATE_ARTICLE",  2);    //添加文章
define("MODIFY_ARTICLE",  4);    //修改文章
define("DELETE_ARTICLE",  8);    //删除文章
define("SHARCH_ARTICLE",  16);    //搜索文章
define("CREATE_COMMENT",  32);    //添加文章评论
define("DELETE_COMMENT",  64);    //删除文章评论
 
//所有的权限
$final_allow = PUBLIC_ARTICLE | CREATE_ARTICLE | MODIFY_ARTICLE | DELETE_ARTICLE 
  | SHARCH_ARTICLE | CREATE_COMMENT | DELETE_COMMENT;
 
echo "管理者拥有的全部权限:" .decbin($final_allow). "<br>";
 
$no_shearch_allow = $final_allow ^ SHARCH_ARTICLE;
echo "仅无法搜索文章的权限:" .decbin($no_shearch_allow). "<br>";
 
//编辑人员独有的权限
$editor_allow = PUBLIC_ARTICLE | MODIFY_ARTICLE | DELETE_ARTICLE;
$no_editor_allow = $final_allow & ~$editor_allow;
echo "非编辑人员所有的权限:" .decbin($no_editor_allow). "<br>";
?>

运行结果:

image-20220111023751530

示例2

比如后台工具的管理权限

//定于权限 2的n次方
var ADD = 1; // 增加权限
var UPD = 2; // 修改权限
var SEL = 4; // 查找权限
var DEL = 8; // 删除权限

// 给予某种权限用到"位或"运算符
var GROUP_A = ADD | UPD | SEL | DEL; // A 拥有增删改查权限
var GROUP_B = ADD | UPD | SEL; // B 拥有增改查权限
var GROUP_C = ADD | UPD; // C 拥有增改权限

// 禁止某种权限用"位与"和"位非"运算符
$GROUP_D = GROUP_C & ~UPD; // D 只拥有了增权限


//检测某个用户是否有这个权限
console.log("A用户组成员是否有增加权限"+ ((GROUP_A & ADD) > 0))
console.log("A用户组成员是否有删除权限"+ ((GROUP_A & DEL) > 0))

console.log("B用户组成员是否有增加权限"+ ((GROUP_B & ADD) > 0))
console.log("B用户组成员是否有删除权限"+ ((GROUP_B & DEL) > 0))

console.log("C用户组成员是否有增加权限"+ ((GROUP_C & ADD) > 0))
console.log("C用户组成员是否有删除权限"+ ((GROUP_C & DEL) > 0))

console.log("D用户组成员是否有增加权限"+ ((GROUP_C & ADD) > 0))
console.log("D用户组成员是否有删除权限"+ ((GROUP_C & DEL) > 0))

示例3

在Linux文件系统中,一个用户对文件或目录所拥有的权限分为三种:"可读"、"可写"和"可执行",分别用 1 、2 和 4 来表示,它们之间可以任意组合:有"可读"、"可写"权限就用 3 来表示(1 + 2 = 3);有"可读"、"可执行"权限就用5来表示(1 + 4 = 5),三种权限全部拥有就用 7 表示(1 + 2 + 4 = 7)
实际上,这种运算是基于二进制的。

image-20220111023319849

假设可执行、可写、可读三种权限分别对应三个状态位,如果用户具有某种权限,那么将对应的状态位标识为"1",反之则标识为"0"

代码示例

//定义权限
var READ = 1<< 0; // 把可读权限放在最右边
var WRITE = 1<<1; // 可读权限向左移一位
var EXCUTE = 1<<2; // 可执行权限向左移两位

//赋予权限
var USER_TYL = READ | WRITE; //设置权限读和写

//验证权限
console.log("USER_TYL可读:"+ ((USER_TYL & READ) > 0));
console.log("USER_TYL可写:"+ ((USER_TYL & WRITE) > 0));
console.log("USER_TYL可执行:"+ ((USER_TYL & EXCUTE) > 0));

将这个代码直接贴到浏览器控制台,即可调试(谷歌浏览器快捷键 ctrl+shift+j

科普

参考资料:

https://www.php.net/decbin

https://blog.csdn.net/weixin_30832405/article/details/98915959

https://blog.csdn.net/ackwie8024934/article/details/101685715

https://www.cnblogs.com/tangyongle/p/7499787.html

https://www.jianshu.com/p/d75b0a461380

最后修改:2022 年 01 月 11 日 03 : 05 AM

发表评论