Front-end permission control design based on bit operations

Binary can generally represent 32 states, and each bit can represent a different permission value. Suppose we have four permission values, namely addition, deletion and modification:

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

After we have the permission values, we can use bit operations to combine the permission values. If the corresponding bit is 1, it means there is permission, and 0 means there is no permission.

Prerequisite knowledge of bit operations involved:

Add new permissions - bitwise OR |

The bitwise OR operation is all 0, and a 1 is 1, so the corresponding bit is 0 when there is no permission, and the corresponding bit of the bitwise OR operation is 1 when the permission value is high.

Remove permissions - bitwise XOR^

The bitwise XOR operation means that the same bit is 0 and the different bit is 1, so the permission on the corresponding bit is 1, and the permission value to be removed is also 1. If the two are the same, the corresponding bit is 0. Here we introduce the bitwise OR, but there is no Using it, another better way is adopted, see the code

Determine whether there is a certain permission-bitwise AND&

The bitwise AND operation is all 1, and a 0 is 0. Therefore, if there is permission, the result of bitwise AND on the corresponding bit must be 1. If the corresponding bit is 0, then the result is 0. To determine whether there is permission, only Just check if the result is not equal to 0

Permission operation code:

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

The advantage of this design is that we can combine permission values ​​arbitrarily. For example, users can both add and modify, then combining Create and Update can mean that adding and removing are very flexible, whether it is permission control of different operation types or Page access control is very convenient. 32-bit binary can represent 32 pages, and a 64-bit system can represent 64 pages. Our usual application bits are basically enough.

Guess you like

Origin blog.csdn.net/Suk__/article/details/128666543