前端基于位运算的权限控制设计

二进制一般能表示32个状态,每一个位上都可以表示不同的权限值,假设我们有四个权限值,分别是增删改:

enum Permission {
  Create = 0b0001, // 新增
  Delete = 0b0010, // 删除
  Update = 0b0100, // 修改
}

有了权限值之后,我们就可以用位运算来对权限值进行组合,对应位为1则为有权限,0则没有

涉及到到的位运算前置知识:

新增权限-按位或|

按位或运算是都为0为0,有一个1就是1,所以没权限时对应位为0,按位或上权限值对应位上就是1了

移除权限-按位异或^

按位异或运算是相同为0不同为1,所以对应位上的权限是1,要移除的权限值也是1,两者相同对应位上就是0了,这里介绍一下按位或,但是没有使用它,采用了另一种更好的方式,见代码

判断是否有某个权限-按位与&

按位与运算是都为1为1,有一个0就是0,所以有权限的话对应位按位与上权限值结果肯定是1,如果对应位上是0那么结果就是0,判断是否有权限只看结果是否不等于0即可

权限操作代码:

enum Permission {
  Create = 0b0001,
  Delete = 0b0010,
  Update = 0b0100,
}
const NotHavePermission = 0 // 没有权限
/**
 * @description 组合权限
 * @param userPermission 用户的权限散列值
 * @param permission 要组合的权限
 * @return 如果包含要移除的权限则返回被移除的权限,否则返回null
 */
const combineRolePermissions = (
  userPermission: number,
  ...roleList: Permission[]
): number => {
  return roleList.reduce((prev, curr) => {
    if (!hasPermission(prev, curr)) {
      prev = curr | prev // | 是有一个是0就是0 都为1则为1
    }
    return prev
  }, userPermission)
}
/**
 * @description 移除权限
 * @param userPermission 权用户的权限散列值
 * @param permission 要移除的权限
 * @return 如果包含要移除的权限则返回被移除的权限,否则返回null
 */
const removePermission = (
  userPermission: number,
  targetPermission: Permission
): number | null => {
  if (!hasPermission(userPermission, targetPermission)) {
    return null
  }
  // 异或相同为0不同为1 所以都是1则那位变成0就删除了
  // return userPermission ^ targetPermission; // 异或可以删除但是得先判断是否有该权限,如果当userPermission为0000时不会删除,所以用第二种方式不会出现这种问题
  return (userPermission &= ~targetPermission) // react源码里移除也是这么做的
}
/**
 * @description 是否有某个权限
 * @param userPermission 权用户的权限散列值
 * @param targetPermission 是否包含的权限
 * @returns
 */
const hasPermission = (
  userPermission: number,
  targetPermission: Permission
): boolean => {
  return (userPermission & targetPermission) !== NotHavePermission // &就是有一个为1就是1 都为0则为0
}
let userPermission = NotHavePermission // 用户初始化权限是什么都没有就是0
// 后端返回的权限集合
const permissionCollections = [Permission.Create, Permission.Update]
// 组合后端返回的权限
userPermission = combineRolePermissions(
  userPermission,
  ...permissionCollections
)
console.log('用户权限:', userPermission.toString(2)) // 0101
console.log('是否有删除权限', hasPermission(userPermission, Permission.Delete)) // false
userPermission = removePermission(userPermission, Permission.Create) // 移除新增权限
console.log('删除新增后:', userPermission.toString(2)) // 0100

这样设计的好处就是我们可以任意的组合权限值,比如用户既能新增又能修改,那么组合Create和Update即可表示,新增和移除都很灵活, 不管是不同操作类型的权限控制还是页面的访问权限控制都很方便,二进制32位能表示32个页面,64位系统能表示64个页面,我们平时的应用位数基本上够用了

猜你喜欢

转载自blog.csdn.net/Suk__/article/details/128666543
今日推荐