前端 RBAC 許可權方案

語言: CN / TW / HK

在做中後臺管理系統系統時,許可權是非常重要的一個功能。許可權的方案非常多,在眾多方案中,最常用的便是 RBAC 模型。下面結合之前參與的幾個專案,介紹下基於 RBAC 的一些簡單實現方案。

術語描述

  • 使用者:操作的賬號,為許可權的載體
  • 資源:將頁面(路由)、頁面內容、資料,介面等可以進行許可權控制的都稱為資源。
  • 角色:許可權的載體,通常是指具有某些共同特徵的一組人,比如財務、運維、研發等角色;角色和許可權(資源)繫結,通過不同的角色關聯不同的許可權

常見的許可權模型

  • ACL(Access Control List):訪問控制列表,直接將許可權與使用者繫結,當用戶數量很多的時候,操作一次許可權就需要對每個使用者都進行授權,工作量很大。
  • RBAC(Role-Based Access List): 基於角色的許可權控制,通過 使用者 -> 角色 -> 許可權 的模型,增加了一層角色來間接的賦予使用者許可權,從而讓使用者與許可權解耦。
  • ABAC(Attribute-Based Access Control): 基於屬性的訪問控制,通過定義一系列屬性(使用者屬性、環境屬性、資源屬性),通過動態計算來確定使用者是否有許可權訪問。對於資源的管控力度更細,比如運營(角色)在北京(環境)能查詢北京訂單(資源)。這種在前端並不常見,有興趣自行了解。

前端的許可權控制

前端對許可權控制粒度的不同,可以分為:

  • 頁面許可權:包括登入許可權、路由、選單這類,本質上就是對路由進行控制。
  • 頁面內容許可權:比如沒有編輯許可權,則隱藏掉相關的UI元件,或者不同許可權則展示不同資料,通常和後臺介面掛鉤。

角色固定/較少的方案

這種應該是目前比較常見的一種,角色以及對應的許可權由後臺維護,前端通常會維護一份選單(路由)與角色的 map 配置,例如:

typescript const menusConfig = [ { path: '/path1', meta: { title: 'path1', roles: ['role1', 'role2', 'role3'] // 該條路由那些角色可以訪問 } }, { path: '/path2', meta: { title: 'path2', roles: ['role1', 'role2'] } }, { path: '/path3', meta: { title: 'path3', roles: ['role3'] } } ]

這份配置一般維護在前端,流程通常是:

  1. 開啟站點,登入
  2. 從後臺獲取到當前使用者的角色
  3. 根據該角色,生成有許可權的路由和選單,進行頁面初始化

使用者的 角色 屬性,需要在建立的時候繫結,可以提供一個 使用者管理 的模組進行配置。

頁面許可權

雖然流程在第三步生成的選單後,頁面上不存在入口讓使用者點選進入,但如果使用者記住某條路由(比如儲存到書籤),直接用過url進入,那麼還是會開啟的。所以還需要在路由層面做許可權判斷,如果沒有許可權,則跳轉403頁面。

vue 和 react 的路由攔截都有各自的實現,這裡不列出來,只給出主要邏輯虛擬碼

```typescript const {enableView} = usePermisesion();

if (!enableView) { // 定向到 403 頁面 } else { // 正常邏輯 } ```

這裡的 usePermisesion 通過 menusConfig 和 使用者角色 來判斷是當前路由是否許可權進入,使用者角色 建議通過全域性狀態、context之類的注入。

當然這裡簡化了操作,例如應該先進行 404 的判斷,否則隨便輸入的 url 都會跳轉到 403

內容許可權控制

內容許可權是比較難處理的,不像頁面許可權可以通過全域性的攔截器進行統一的攔截,需要通過侵入業務程式碼中。

一些實現方案是將許可權需要的角色寫到業務中處理:

```jsx