經典「用戶-角色-權限」模型在新增業務場景(模塊、菜單、按鈕、行級、列級…)時,需不斷添加關聯表(用戶-模塊、角色-菜單、用戶-按鈕…),導致表爆炸、查詢複雜、維護困難。
將六張關聯表**合併為單表 privilege**,以三元組唯一確定一條授權記錄。
CREATE TABLE privilege (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
privilege_master VARCHAR(20) NOT NULL COMMENT '主體類型: USER/ROLE/DEPT',
privilege_master_value BIGINT NOT NULL COMMENT '主體ID',
privilege_access VARCHAR(20) NOT NULL COMMENT '領域類型: MENU/BUTTON/API/ROW/COL',
privilege_access_value VARCHAR(100) NOT NULL COMMENT '領域編碼/ID',
privilege_operation VARCHAR(20) NOT NULL COMMENT '操作: ENABLED/DISABLED/GRANT/DELEGATE',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_master_access_op (privilege_master, privilege_master_value, privilege_access, privilege_access_value, privilege_operation)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
| 業務場景 | privilege_master | privilege_master_value | privilege_access | privilege_access_value | privilege_operation |
|---|---|---|---|---|---|
| 角色「銷售」可見「客戶管理」菜單 | ROLE | 1001 | MENU | MNU_CUSTOMER | ENABLED |
| 用戶 10001 可點擊「導出」按鈕 | USER | 10001 | BUTTON | BTN_EXPORT | ENABLED |
| 禁止用戶 10002 訪問「薪資」頁面 | USER | 10002 | MENU | MNU_SALARY | DISABLED |
| 部門 200 可分配「報表」權限 | DEPT | 200 | API | /api/report/* | GRANT |
-- 判斷用戶是否有某操作權限(含角色繼承)
SELECT 1 FROM privilege
WHERE privilege_operation IN ('ENABLED','GRANT')
AND privilege_access = 'BUTTON'
AND privilege_access_value = 'BTN_DELETE'
AND (
(privilege_master = 'USER' AND privilege_master_value = ?)
OR (privilege_master = 'ROLE' AND privilege_master_value IN (SELECT role_id FROM user_role WHERE user_id = ?))
OR (privilege_master = 'DEPT' AND privilege_master_value IN (SELECT dept_id FROM user_dept WHERE user_id = ?))
)
LIMIT 1;
privilege_access='ROW', access_value='table:pk_value'privilege_access='COL', access_value='table:column'privilege_operation='DELEGATE' + 有效期字段**零 DDL 變更**,僅應用層新增枚舉值即可支撐。
PermissionService.check(user, domain, operation) 統一入口perm:user:{uid}),變更時發布失效事件一張表、三個維度、無限擴展——這才是權限模型的「終極簡潔」。