RBAC(Role-Based Access Control):基於角色的存取控制。不直接將權限指派給使用者,而是:
使用者權限 = 其所屬角色權限的聯集。人員異動時只需調整角色指派,權限自動生效。
| 維度 | 傳統 ACL(使用者-權限直接綁定) | RBAC(角色中介) |
|---|---|---|
| 新增使用者 | 需逐一勾選數十項權限,易遺漏/錯誤 | 選擇預定角色(如「編輯」),秒級完成 |
| 權限調整 | 逐個使用者修改,大量帳號極其繁瑣 | 修改角色權限,所有隸屬使用者即時生效 |
| 離職/轉崗 | 需清理個人權限殘留 | 移除角色指派或改派新角色 |
| 權限稽核 | 難以追蹤「誰有什麼權限」 | 清晰:角色→權限、使用者→角色 |
| 適用規模 | 極小系統(<10 人、<20 權限點) | 中大型系統、多部門、多層級組織 |
-- 角色表
CREATE TABLE think_role (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL COMMENT '角色標識',
title VARCHAR(50) COMMENT '角色顯示名',
status TINYINT DEFAULT 1,
remark VARCHAR(255)
);
-- 節點/權限表(對應控制器/方法)
CREATE TABLE think_node (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL COMMENT '節點名稱(如 User/add)',
title VARCHAR(50) COMMENT '顯示名稱',
pid INT DEFAULT 0 COMMENT '父節點(模組/控制器層級)',
level TINYINT DEFAULT 1 COMMENT '層級:1模組 2控制器 3方法',
status TINYINT DEFAULT 1,
sort INT DEFAULT 0
);
-- 角色-節點關聯表
CREATE TABLE think_access (
role_id INT NOT NULL,
node_id INT NOT NULL,
level TINYINT NOT NULL,
module VARCHAR(50),
PRIMARY KEY (role_id, node_id)
);
-- 使用者-角色關聯表
CREATE TABLE think_role_user (
role_id INT NOT NULL,
user_id INT NOT NULL,
PRIMARY KEY (role_id, user_id)
);
config.php 設定 'RBAC_SUPERADMIN' => 'admin'(超管帳號)、'ADMIN_AUTH_KEY' => 'userId'。import('ORG.Util.Rbac');(ThinkPHP 3.x)或使用 5.x 社群擴充套件。// 登入成功後
Rbac::saveAccessList($userId); // 將用戶所有權限節點寫入 Session/快取
class CommonController extends Controller {
protected function _initialize() {
if (!Rbac::AccessDecision()) {
$this->error('無權限存取');
}
}
}
// 業務控制器繼承 CommonController 即自動受保護
{{-- 模板中 --}}
{volist name="__MENU__" id="vo"}
{if condition="Rbac::checkAccess($vo['name'])"}
<a href="{:U($vo['name'])}">{$vo['title']}</a>
{/if}
{/volist}
Controller 類別的 public 方法自動生成節點記錄。{if condition="Rbac::checkAccess('User/delete')"}<button>刪除</button>{/if}。模組/控制器/方法(如 Admin/User/add),對應路由結構。RBAC_SUPERADMIN,程式碼首行判斷直接返回 true。Rbac::checkAccess()。RBAC 透過「角色」解耦「使用者」與「權限」,是中大型系統權限管理的標準解法。ThinkPHP 內建/社群擴充套件提供開箱即用的實作,關鍵在於節點設計規範化、快取策略正確、視圖層動態渲染三大落地細節。