位运算--vue权限路由的另外一种思路

RBAC0(基于角色的访问控制)

Role-Based Access Control:使用角色描述用户和权限(operation+resource)之间的关系,用户和权限之间无需直接关联前端

RBAC 基本模型如图所示(图片来自有赞权限系统):vue

clipboard.png

本质上,角色就是一组权限的集合。git

VUE权限路由的实现方案

0x01

后端表结构:github

clipboard.png

在项目中须要进行权限控制的路由多是动态变化的。也许领导说某个页面如今不须要权限控制,而后过两天又须要了。。。
因此在后端维护一张route表,每一个路由对应一条记录,id自增,记录路由的url,是否启用等。这样全部须要权限控制的路由都分配了一个惟一id。后端

上面说到角色的本质是一组权限的集合,那么能够用int型的二进制位来表示这个集合,0表示没有权限,1表示有权限。
在JavaScript中,按位操做符(Bitwise operators)将其操做数(operands)看成32位的比特序列(由0和1组成)。rout表的id与比特序号进行关联。例如50的二进制表示为110010,那么表示有id为2,5,6的路由的访问权限。routes表的里id值表示控制这条路由权限在二进制位中的序号。async

role_route表中的permissions和offset字段描述了一个角色所拥有的权限,表示为{(offset1,permissions1),(offset2,permissions2)…(offsetN,permissionsN)}。即用permissions和offset字段关联routes表的id。例如某个角色在role_route表中有两条记录offset为0,permissions为1和offset为1,permissions为2,那么这个角色完整的二进制集合为10(省略30个0)1,在routes表中所关联的路由id为1和33,即这个角色拥有路由id为1和33的权限。post

0x02

在前端判断一个路由是否有权限:url

const permissionUtils = {
  getSingleRoutePermission (id) {
    return 1 << (id % 31)
  },
  getOffset (id) {
    return Math.floor(id / 31)
  },
}

// 假设当前用户拥有的角色在role_route表中关联两条记录: offset为0,permissions为100和offset为1,permissions为50
const permissions = [100, 50] // offset分别为0,1
permissionUtils.getSingleRoutePermission(routeId) & permissions[permissionUtils.getOffset(routeId)]

给某个角色增长一个权限:spa

let offset = permissionUtils.getOffset(routeId)
permissions.splice(offset, 1, permissions[offset] |= permissionUtils.getSingleRoutePermission(routeId))

0x03

这里简单描述一下vue-element-admin实现权限路由的思路。code

/**
 * asyncRoutes
 * the routes that need to be dynamically loaded based on user roles
 */
const asyncRoutes = [
  {
    path: '/permission',
    component: Layout,
    name: 'Permission',
    meta: {
      roles: ['admin', 'editor']
    }
  }
]
router.addRoutes(asyncRoutes.reduce((permissionRoutes, route) => {
  user.roles.some(role => route.meta.roles.includes(role)) && permissionRoutes.push(route)
  return permissionRoutes
}, []))

这里能够看到某个路由的访问权限是写在路由定义里的,对于自定义角色和角色较多的状况不太好处理。上面咱们使用角色来存储路由的访问权限,实现将路由的定义和权限控制分开。

0x04

使用二进制序列来存储路由权限,对于多角色和自定义角色有很好的支持。

对于用户自定义角色的状况,咱们只须要将须要管理的路由id设置到对应的二进制位便可,不影响路由的定义,且能够无限建立角色。

对于多角色的状况,只要将用户的全部角色作|操做便可,例如 角色1|角色1|···角色N

在角色数量和路由数量大的状况下,使用二进制位方式管理权限应该是不错的选择。

0x05

这里并无对路由和菜单是否分离,路由是否由后端返回以及是否使用全局路由守卫等问题进行讨论,使用二进制位存储权限能够与这几种方式相结合,具体选择看业务和我的喜爱。

对于路由和菜单的管理能够看看这篇文章的总结:vue权限路由实现方式总结

连接:

有赞权限系统

vue-element-admin

相关文章
相关标签/搜索