位運算--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

相關文章
相關標籤/搜索