揭秘位掩码权限设计的神秘面纱

2023年 7月 17日 47.9k 0

在权限设计中有一种非常独特且有意思方案叫位掩码权限设计,它在应对一些局部数据权限(权限点不多)的场景下,非常的犀利,比如 PingCode 知识管理页面权限就结合 ACL 对特定人群(用户、用户组、部门)做权限分配,最近做的一个低代码项目中的某块业务也表现很突出,多次尝到甜头分享给大家

什么是位掩码权限?

维基百科搜了一下没有正式对位掩码权限的解释,还得是 ChatGPT:

位掩码权限(Bitmask Permissions)是一种权限管理系统,用于在计算机系统中对资源或操作进行控制和限制。它使用二进制位来表示不同的权限或访问级别。每个二进制位都代表一种权限或操作,可以设置为开启或关闭。

了解过 Linux 权限的应该知道它的一些权限点:r(read 读)、w(write 写)、x(execute 执行),对应的权限值是 4、2、1。

这是一个标准的位掩码权限设计,其中 1、2、4 对应着基于“位”的二进制,拿 4 位举例: 1 => 00012 => 00104 => 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 了)

    实际应用

    需求界面是这样的:

    image.png

    对应填写表单是这样的:

    image.png

    选型

    选用哪门技术/手段,必然要考虑各种因素(业务场景、已有架构、易用、质量、性能),这里简单介绍一些前置条件:

  • 低代码场景,主体表(是一个抽象节点,后续简称业务主体)是动态表,动态字段
  • 关系型数据库(选用的原因是这块业务框架指定了 MySQL)
  • 权限粒度是字段,且权限点有限
  • 权限绑定的用户主体(成员/部门/组织角色/应用角色/职位)分布于不同的表
  • 针对于上述条件可以得出的结论就是本文讲的 位掩码权限的设计方案, 其实中间环节是可以有很多思考的(不感兴趣的可以跳过) 一些结论:

  • 关系型数据库,权限值不推荐是列表(对象、数组),一是不支持,存 json 串也比较膈应,最好 用基本数据类型(字符串、数字)
  • 权限绑定的用户主体分布多表,需要 排除关联表的方案,采用关联字段的方式 ,如果采用关联表方案有以下弊端:
  • 分布于多个主体关联权限表,缺点是 表分散,成本高 ,在动态表的情况下额外在创建动态表也很费劲,后续根据不同主体找不同的表。
  • 分布于一张表存多个主体映射权限的数据,缺点是主体(这里是配置的模块)数量不固定,比较 容易造成数据量大 ,总数是:业务主体数据量 * 用户主体数量 * 权限点数量,所以后续还要 考虑分表 。
  • 无论上面哪种都需要 额外多查一次关联表
  • 权限值的储存如果是 01 拼接的字符串(0 代表无权限,1 代表有权限),那么需要考虑权限值的展示以及单字段校验等方式,因为字符串一个字符映射一个权限点,所以前端展示时需要知道哪一位对应什么权限,这种情况下前后端都必然要有一个 权限点索引配置,还得有一套根据索引匹配的逻辑 。
  • 选用位掩码权限的方式有这些优势:

  • 数字作为基本数据类型, 在任何数据库都支持 ,而数组或 JSON 需要 NoSQL 类的数据库支撑。
  • 数字相比列表或字符串更简单, 不用考虑权限点映射顺序的相关配置和计算程序 。
  • 数字相比关联列表更简单 ,减少查表次数,内聚性高(与业务主体绑定更近) , 更节约内存 (主要是字段和表之间的对比)
  • 权限值用数字更简洁,在多层嵌套的 JSON 下,显然 数字比对象或数组更清楚 。
  • permissions: {
      read: true,
      write: true,
      require: true
    }
    // good
    permissions: 7
    

    最后

    还是重复两点吧:

  • 权限点小于 6 个,选用此方案非常适合,否则不要使用。
  • 用户主体类型复杂的情况可以结合 ACL 或 RBAC 混合使用。
  • 最后提供可以直接使用的代码片段:

  • 定义权限点
  • image.png

  • 验证工具函数
  • image.png

  • HTML 中方便的管道
  • image.png

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论