注册

前端按钮/组件权限管理

最近项目中遇到了按钮权限管理的需求,整理了一下目前的方案,有不对的地方望大家指出~

方案1:数组+自定义指令

把权限放到数组中,通过vue的自定义指令来判断是否拥有该权限,有则显示,反之则不显示

我们可以把这个按钮需要的权限放到组件上

<el-button
v-hasPermi="['home:advertising:update']"
>新建</el-button>

自定义指令:

逻辑就是我们在登陆后会获取该用户的权限,并存储到localStorage中,当一个按钮展示时会判断localStorage存储的权限列表中是否存在该按钮所需的权限。

/**
* 权限处理
*/

export default {
 inserted(el, binding, vnode) {
   const { value } = binding;
   const SuperPermission = "superAdmin"; // 超级用户,用于开发和测试
   const permissions = localStorage.getItem('userPermissions')&& localStorage.getItem('userPermissions').split(',');
// 判断传入的组件权限是否符合要求
   if (value && value instanceof Array && value.length > 0) {
     const permissionFlag = value;
     const hasPermissions = permissions && permissions.some(permission => all_permission === permission || permissionFlag.includes(permission));
// 判断是否有权限是否要展示
     if (!hasPermissions) {
       el.parentNode && el.parentNode.removeChild(el);
    }
  } else {
     throw new Error(`请设置操作权限标签值`);
  }
},
};

注册权限

import Vue from 'vue';
import Vpermission from "./permission";

// 按钮权限 自定义指令
Vue.directive('permission', Vpermission);

关于路由权限

数组的方案也可以用到菜单权限上,可以在路由的meta中携带该路由所需的权限,例如:

const router = [{
 path: 'needPermissionPage',
 name: 'NeedPermissionPage',
 meta: {
   role: ['permissionA', 'permissionB'],
},
}]

这个时候就需要在渲染权限的时候动态渲染了,该方案可以看一下其他的文章或成熟的项目,写的非常好

方案2: 二进制

通过二进制来控制权限:

假设我们有增删改查四个基本权限:

const UPDATE = 0b000001;
const DELETE = 0b000010;
const ADD = 0b000100;
const SEARCH = 0b001000;

每一位代表是否有该权限,有该权限则是1,反之是0

表达权限:

我们可以使用或运算来表达一个权限结果,或运算:两个任何一个为1,结果就为1

const reslut = UPDATE | DELETE | SEARCH;
console.log(reslut);  // 11

变成了十进制,我们可以通过toString方法变为二进制结果

const reslut = UPDATE | DELETE | SEARCH;
console.log(reslut.toString(2));  // 1011

result 这个结果就代表我们既拥有更新权限,同时也拥有删除和查询的权限

那么我们可以将十进制的reslut当作该用户的权限,把这个结果给后台,下次用户登陆后只需要返回这个结果就可以了。

权限判断

我们了解了如何表达一个权限,那如何做权限的判断呢?

可以通过且运算,且运算:两位都为1,这一位的结果才是1。

还是用上面的结果,当我们从接口中拿到了reslut,判断他是否有 DELETE 权限:

console.log((reslut & DELETE) === DELETE);  // true

是否有新增的权限

console.log((result & ADD) === ADD); // false

判断和使用

/**
* 接受该组件所需的权限,返回用户权限列表是否有该权限
* @param {String} permission
* @returns {Boolean}
*/
function hasPermission(permission) {
 const permissionList = {
   UPDATE: 0b000001,
   DELETE: 0b000010,
   CREATE: 0b000100,
   SEARCH: 0b001000
}
 let btnPermission = permissionList[permission] ? permissionList[permission] : -1;
 if (btnPermission === -1) return false;
 const userPermission = localStorage.getItem('userPermissions');
// 将本地十进制的值转换为二进制
 const userPermissionBinary = userPermission.toString(2);
// 对比组件所需权限和本地存储的权限
 return (userPermissionBinary & btnPermission) === btnPermission;
}

直接在组件中通过v-show/v-if来控制是否展示

<el-button v-show="hasPermission('UPDATE')">更新</el-button>

小结

我理解来说,对于方案1来说,方案2的优势在于更简洁,后台仅需要存储一个十进制的值,但如果后期新增需求更新了新的权限,可能需要调整二进制的位数来满足业务需求。方案1的优势在于更加易懂,新增权限时仅需要更新组件自定义指令的数组。

原文:https://juejin.cn/post/7142778249171435551





0 个评论

要回复文章请先登录注册