結合RBAC模型講解許可權管理系統需求及表結構建立
在本號之前的文章中,已經為大家介紹了很多關於Spring Security的使用方法,也介紹了RBAC的基於角色許可權控制模型。但是很多朋友雖然已經理解了RBAC控制模型,但是仍有很多的問題阻礙他們進一步開發。比如:
- RBAC模型的表結構該如何建立?
- 具體到某個頁面,某個按鈕許可權是如何控制的?
- 為了配合登入驗證表,使用者表中應該包含哪些核心欄位?
- 這些欄位與登入驗證或許可權分配的需求有什麼關係?
那麼本文就希望將這些問題,與大家進行一下分享。
一、回顧RBAC許可權模型
- 使用者與角色之間是多對多的關係,一個使用者有多個角色,一個角色包含多個使用者
- 角色與許可權之間是多對多關係,一個角色有多種許可權,一個許可權可以屬於多個角色
上圖中:
- User是使用者表,儲存使用者基本資訊
- Role是角色表,儲存角色相關資訊
- Menu(選單)是許可權表,儲存系統包含哪些選單及其屬性
- UserRole是使用者和角色的關係表
- RoleMenu是角色和許可權的關係表
本文講解只將許可權控制到選單的訪問級別,即控制頁面的訪問許可權。如果想控制到頁面中按鈕級別的訪問,可以參考Menu與RoleMenu的模式同樣的實現方式。或者乾脆在menu表裡面加上一個欄位區別該條記錄是選單項還是按鈕。
為了有理有據,我們參考一個比較優秀的開源專案:若依後臺管理系統。
二、組織部門管理
2.1.需求分析
之所以先將部門管理提出來講一下,是因為部門管理沒有在我們上面的RBAC許可權模型中進行提現。但是部門這樣一個實體仍然是,後端管理系統的一個重要組成部分。通常有如下的需求:
- 部門要能體現出上下級的結構(如上圖中的紅框)。在關係型資料庫中。這就需要使用到部門id及上級部門id,來組合成一個樹形結構。這個知識是SQL學習中必備的知識,如果您還不知道,請自行學習。
- 如果組織與使用者之間是一對多的關係,就在使用者表中加上一個org_id標識使用者所屬的組織。原則是:實體關係在多的那一邊維護。比如:是讓老師記住自己的學生容易,還是讓學生記住自己的老師更容易?
- 如果組織與使用者是多對多關係,這種情況現實需求也有可能存在。比如:某人在某單位既是生產部長,又是技術部長。所以他及歸屬於技術部。也歸屬於生產部。對於這種情況有兩種解決方案,把該人員放到公司級別,而不是放到部門級別。另外一種就是從資料庫結構上建立User與Org組織之間的多對多關係。
- 組織資訊包含一些基本資訊,如組織名稱、組織狀態、展現排序、建立時間
- 另外,要有基本的組織的增刪改查功能
2.2 組織部門表的CreateSQL
以下SQL以MySQL為例:
CREATE TABLE `sys_org` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`org_pid` INT(11) NOT NULL COMMENT '上級組織編碼',
`org_pids` VARCHAR(64) NOT NULL COMMENT '所有的父節點id',
`is_leaf` TINYINT(4) NOT NULL COMMENT '0:不是葉子節點,1:是葉子節點',
`org_name` VARCHAR(32) NOT NULL COMMENT '組織名',
`address` VARCHAR(64) NULL DEFAULT NULL COMMENT '地址',
`phone` VARCHAR(13) NULL DEFAULT NULL COMMENT '電話',
`email` VARCHAR(32) NULL DEFAULT NULL COMMENT '郵件',
`sort` TINYINT(4) NULL DEFAULT NULL COMMENT '排序',
`level` TINYINT(4) NOT NULL COMMENT '組織層級',
`status` TINYINT(4) NOT NULL COMMENT '0:啟用,1:禁用',
PRIMARY KEY (`id`)
)
COMMENT='系統組織結構表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
注意:mysql沒有oracle中的start with connect by的樹形資料彙總SQL。所以通常需要為了方便管理組織之間的上下級樹形關係,需要加上一些特殊欄位,如:org_pids:該組織所有上級組織id逗號分隔,即包括上級的上級;is_leaf是否是葉子結點;level組織所屬的層級(1,2,3)。
三、選單許可權管理
3.1 需求分析
- 由上圖可以看出,選單仍然是樹形結構,所以資料庫表必須有id與menu_pid欄位
- 必要欄位:選單跳轉的url、是否啟用、選單排序、選單的icon向量圖示等
- 最重要的是選單要有一個許可權標誌,具有唯一性。通常可以使用選單跳轉的url路徑作為許可權標誌。此標誌作為許可權管理框架識別使用者是否具有某個頁面檢視許可權的重要標誌
- 需要具備選單的增刪改查基本功能
- 如果希望將選單許可權和按鈕超連結相關許可權放到同一個表裡面,可以新增一個欄位。使用者標誌該許可權記錄是選單訪問許可權還是按鈕訪問許可權。
3.2 選單許可權表的CreateSQL
CREATE TABLE `sys_menu` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`menu_pid` INT(11) NOT NULL COMMENT '父選單ID',
`menu_pids` VARCHAR(64) NOT NULL COMMENT '當前選單所有父選單',
`is_leaf` TINYINT(4) NOT NULL COMMENT '0:不是葉子節點,1:是葉子節點',
`name` VARCHAR(16) NOT NULL COMMENT '選單名稱',
`url` VARCHAR(64) NOT NULL COMMENT '跳轉URL',
`icon` VARCHAR(45) NULL DEFAULT NULL,
`icon_color` VARCHAR(16) NULL DEFAULT NULL,
`sort` TINYINT(4) NULL DEFAULT NULL COMMENT '排序',
`level` TINYINT(4) NOT NULL COMMENT '選單層級',
`status` TINYINT(4) NOT NULL COMMENT '0:啟用,1:禁用',
PRIMARY KEY (`id`)
)
COMMENT='系統選單表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
四、角色管理
上圖為角色修改及分配許可權的頁面
4.1.需求分析
- 角色本身的管理需要注意的點非常少,就是簡單的增刪改查。重點在於角色分配該如何做。
- 角色表包含角色id,角色名稱,備註、排序順序這些基本資訊就足夠了
- 為角色分配許可權:以角色為基礎勾選選單許可權或者操作許可權,然後先刪除sys_role_menu表內該角色的所有記錄,在將新勾選的許可權資料逐條插入sys_role_menu表。
- sys_role_menu的結構很簡單,記錄role_id與menu_id,一個角色擁有某一個許可權就是一條記錄。
- 角色要有一個全域性唯一的標識,因為角色本身也是一種許可權。可以通過判斷角色來判斷某使用者的操作是否合法。
- 通常的需求:不會在角色管理介面為角色新增使用者,而是在使用者管理介面為使用者分配角色。
4.2.角色表與角色選單許可權關聯表的的CreateSQL
CREATE TABLE `sys_role` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`role_id` VARCHAR(16) NOT NULL COMMENT '角色ID',
`role_name` VARCHAR(16) NOT NULL COMMENT '角色名',
`role_flag` VARCHAR(64) NULL DEFAULT NULL COMMENT '角色標識',
`sort` INT(11) NULL DEFAULT NULL COMMENT '排序',
PRIMARY KEY (`id`)
)
COMMENT='系統角色表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
CREATE TABLE `sys_role_menu` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`role_id` VARCHAR(16) NOT NULL COMMENT '角色ID',
`menu_id` INT(11) NOT NULL COMMENT '選單ID',
PRIMARY KEY (`id`)
)
COMMENT='角色選單多對多關聯表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
五、使用者管理
5.1.需求分析
- 上圖中點選左側的組織選單樹結點,要能顯示出該組織下的所有人員(系統使用者)。在組織與使用者是一對多的關係中,需要在使用者表加上org_id欄位,用於查詢某個組織下的所有使用者。
- 使用者表中要儲存使用者的使用者名稱、加密後的密碼。頁面提供密碼修改或重置的功能。
- 角色分配:實際上為使用者分配角色,與為角色分配許可權的設計原則是一樣的。所以可以參考。
- 實現使用者基本資訊的增刪改查功能
5.2.sys_user 使用者資訊表及使用者角色關係表的CreateSQL
CREATE TABLE `sys_user` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`org_id` INT(11) NOT NULL,
`username` VARCHAR(64) NULL DEFAULT NULL COMMENT '使用者名稱',
`password` VARCHAR(64) NULL DEFAULT NULL COMMENT '密碼',
`enabled` INT(11) NULL DEFAULT '1' COMMENT '使用者賬戶是否可用',
`locked` INT(11) NULL DEFAULT '0' COMMENT '使用者賬戶是否被鎖定',
`lockrelease_time` TIMESTAMP NULL '使用者賬戶鎖定到期時間',
`expired_time` TIMESTAMP NULL '使用者賬戶過期時間',
`create_time` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '使用者賬戶建立時間',
PRIMARY KEY (`id`)
)
COMMENT='使用者資訊表'
ENGINE=InnoDB
;
CREATE TABLE `sys_user_role` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`role_id` VARCHAR(16) NULL DEFAULT NULL,
`user_id` VARCHAR(18) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
在使用者的資訊表中,體現了一些隱藏的需求。如:多次登入鎖定與鎖定到期時間的關係。賬號有效期的設定規則等。
當然使用者表中,根據業務的不同還可能加更多的資訊,比如:使用者頭像等等。但是通常在比較大型的業務系統開發中,業務模組中使用的使用者表和在許可權管理模組使用的使用者表通常不是一個,而是根據某些唯一欄位弱關聯,分開存放。這樣做的好處在於:經常發生變化的業務需求,不會去影響不經常變化的許可權模型。
期待您的關注
- 向您推薦博主的系列文件:《手摸手教您學習SpringBoot系列-16章97節》
- 本文轉載註明出處(必須帶連線,不能只轉文字):字母哥部落格。