26、生鮮電商平臺-RBAC系統權限的設計與架構
說明:根據上面的需求描述以及對需求的分析,我們得知通常的一個中小型系統對於權限系統所需實現的功能以及非功能性的需求,在下面我們將根據需求從技術角度上分析實現的策略以及基於目前兩種比較流行的權限設計思想來討論關於權限系統的實現。
1.1. 技術策略
l 身份認證
在B/S的系統中,為識別用戶身份,通常使用的技術策略為將用戶的身份記錄在Session中,也就是當用戶登錄時即獲取用戶的身份信息,並將其記錄到Session裏,當需要進行身份認證的時候通過從Session中獲取用戶的身份信息來實現用戶的身份認證。
l 資源權限校驗
資源權限校驗取決於系統的授權模型,這塊將在之後進行詳細的闡述。
l 數據權限校驗
數據權限校驗取決於系統的授權模型,這塊將在之後進行詳細的闡述。
l 授權模型
授權模型作為權限系統的核心,從本質上決定了權限系統的易用性,這個易用性包括權限的授予和權限的校驗,並同時也決定了權限的繼承,權限的排斥和包含等方面的實現。
在經歷了這麽多年的發展,授權模型在目前中小型應用系統接受的比較多的主要有RBAC模型和ACL模型,將在之後展開專門的篇幅進行講解。
l 權限校驗的體現
權限校驗的體現在中小型系統中體現出來的通常只是對於系統菜單、按鈕顯示的控制和對於擁有權限的數據的訪問上。
它們共同依賴於資源權限校驗和數據權限校驗,對於系統菜單、按鈕的顯示上的控制在B/S中通常采用的技術策略為在生成菜單、按鈕的Html時做權限級的判斷,當操作主體不具備權限時則不生成該菜單、按鈕的Html,從技術角度分析為方便使用者,避免使用者調用權限校驗接口,通常的做法為提供菜單、按鈕的標簽,通過此標簽生成的菜單和按鈕即為經過權限過濾的。
l 高性能
為提高權限系統在授權以及校驗權限時的性能,通常的做法為采用緩存技術以及加強權限系統的管理建設,加強權限系統的管理建設有助於建立一個最為適合需求的權限結構,同時做到了簡化系統權限授予。
l 安全性
安全性方面來講在B/S系統中通常有兩個方面需要控制:
n 通過非法途徑訪問系統文件
在Java的Web應用中通常采用的技術策略為將需要受保護的文件放入WEB-INF文件夾中,大家都知道在WEB-INF下的文件除了在服務器上能直接訪問外,通過普通的URL是無法訪問到的。
其次的做法為做Filter,即對需要受保護的資源做訪問的Filter,如操作者不具備權限則直接報出錯誤。
n 通過非法途徑訪問系統操作
通常采用的技術策略為對每個直接暴露對外的需要受權限保護的對象做操作級別的權限控制,簡單來說在Web系統中通常采用MVC框架來實現,通常Command層是直接對外的,為防止用戶通過URL或其他方式訪問Command,從技術上我們需要考慮對現有系統的盡量少的侵入性,所以通常采用的做法是在Command之上做Before Interceptor或Proxy,在此Interceptor或Proxy中做權限的校驗,以確認操作者具有相應的權限。
經過上面的描述,我們已經基本了解到滿足權限系統需求的技術實現策略,從中我們也可以看出權限系統中最為重要的為授權模型,由於權限系統的通用性,在業界也是推出了不少的授權模型,在這裏我們已目前比較通用的兩種授權模型來具體講解權限系統的完整實現。
1.2. 基於RBAC的實現
1.2.1. RBAC介紹
RBAC模型作為目前最為廣泛接受的權限模型,在此也將對其模型進行簡要的介紹,RBAC模型成功的經典應用案例當屬Unix系統了。
NIST(The National Institute of Standards and Technology,美國國家標準與技術研究院)標準RBAC模型由4個部件模型組成,這4個部件模型分別是基本模型RBAC0(Core RBAC)、角色分級模型RBAC1(Hierarchal RBAC)、角色限制模型RBAC2(Constraint RBAC)和統一模型RBAC3(Combines RBAC)[1]。RBAC0模型如圖1所示。
圖表 1 RBAC 0模型
l RBAC0定義了能構成一個RBAC控制系統的最小的元素集合
在RBAC之中,包含用戶users(USERS)、角色roles(ROLES)、目標objects(OBS)、操作operations(OPS)、許可權permissions(PRMS)五個基本數據元素,權限被賦予角色,而不是用戶,當一個角色被指定給一個用戶時,此用戶就擁有了該角色所包含的權限。會話sessions是用戶與激活的角色集合之間的映射。RBAC0與傳統訪問控制的差別在於增加一層間接性帶來了靈活性,RBAC1、RBAC2、RBAC3都是先後在RBAC0上的擴展。
l RBAC1引入角色間的繼承關系
角色間的繼承關系可分為一般繼承關系和受限繼承關系。一般繼承關系僅要求角色繼承關系是一個絕對偏序關系,允許角色間的多繼承。而受限繼承關系則進一步要求角色繼承關系是一個樹結構。
l RBAC2模型中添加了責任分離關系
RBAC2的約束規定了權限被賦予角色時,或角色被賦予用戶時,以及當用戶在某一時刻激活一個角色時所應遵循的強制性規則。責任分離包括靜態責任分離和動態責任分離。約束與用戶-角色-權限關系一起決定了RBAC2模型中用戶的訪問許可。
l RBAC3包含了RBAC1和RBAC2
既提供了角色間的繼承關系,又提供了責任分離關系。
1.2.2. 實現方案
通過上面章節對RBAC的介紹,從RBAC模型中我們可以看出它已經實現了一個使用起來很方便的授權模型,並同時也就權限的繼承,權限的排斥和包含提出了解決的模型。
那麽現在的關鍵是我們需要來看看基於RBAC到底是怎麽實現權限系統的需求的呢?在這裏我們針對在技術策略中未描述的授權模型和權限校驗部分做實現方案的講解。
l 授權模型
授權模型遵循RBAC進行搭建,即建立如上圖表一的模型。
針對授權模型中的幾個關鍵部分我們進行描述:
n 授權
按照RBAC的模型,在授權時分為配置資源以及資源的操作、授予角色對資源的操作權限、分配角色給用戶這幾個步驟來完成。
從這幾個步驟我們進行分析:
u 配置資源以及資源的操作
實現這步非常的簡單,直接維護資源以及資源操作兩個對象的持久即可實現。
u 授予角色對資源的操作權限
實現這步同樣非常的簡單,維護角色與資源的關聯模型即可。
u 分配角色給用戶
實現這步同樣非常的簡單,維護角色與用戶的關聯模型即可。
n 權限的繼承
權限的繼承在RBAC的模型中通過增加角色的自關聯來實現,即角色可擁有子角色,子角色繼承父角色的權限。
按照此模型可以看出在授權時維護權限的繼承也是非常的簡單,維護角色的自關聯模型即可。
n 權限的排斥和包含
權限的排斥和包含這塊我沒有具體看RBAC的規範,通常的做法是通過在資源的操作權限模型中增加自關聯模型以定義哪些資源的操作權限是排斥和包含的,在授權時可以看到同樣需要維護的只是資源權限的自關聯模型。
l 資源權限校驗
根據上面的授權模型,在做資源權限校驗的時候需要經過以下步驟:
n 判斷用戶所在的角色是否擁有對資源進行操作的權限
獲取用戶所擁有的角色,遍歷其角色,以各角色建立Session,並通過類似的role.doPrivilege(Resource,Operation)的方式來判斷該角色是否具備權限,如具備則直接返回,如不具備則直到遍歷結束。
n 遞規用戶所在角色的父角色判斷是否擁有對資源進行操作的權限
當遍歷完用戶本身的角色得到用戶不具備對資源進行該操作的權限時,則開始遞規其所在角色的父角色來判斷是否擁有對資源進行操作的權限,過程同上,如確定某角色具備,則返回,如不具備直到遞規結束。
l 數據權限校驗
在RBAC模型中沒有明確定義數據權限的實現策略,鑒於此首先要講解下基於RBAC模型的數據授權模型的建立,基於RBAC模型,將數據映射為RBAC中的資源,對數據的操作則映射為資源的操作,同樣的是將此資源以及資源的操作構成的權限授予給角色,將用戶分配給角色完成數據權限的授權過程。
但根據數據權限校驗的需求,數據的權限也是需要繼承的,而且數據權限的授予對象需要是多種,這樣的話就對上面根據RBAC映射形成的數據權限的授權模型造成了沖擊,需要重構上面的授權模型來滿足需求。
為實現數據權限的繼承,需要將RBAC模型中的資源重構為允許自關聯的模型,為實現數據權限能夠授予給多種對象,需要將本來資源操作權限授予給角色的模型演變為數據操作權限授予給角色、組織機構或具體人員,根據RBAC模型,同樣的建立一個中間對象,此對象和數據操作權限所授予的對象做1對多的關聯,在經過這樣的重構之後數據權限的授權模型就形成了,也滿足了數據權限的繼承和授予給多種對象的需求。
圖表 2 基於RBAC演變的數據權限模型
上面的圖中少畫了數據的自關聯。
根據上面的數據權限模型,來看看數據權限的校驗是怎麽樣去實現呢?
在做數據權限校驗的時候我們需要實現的為兩種方式,一種是獲取操作主體具有數據操作權限的全部數據,另外一種為分頁獲取操作主體具有數據操作權限的數據。
就這兩種方式分別來進行闡述:
n 獲取操作主體具有數據操作權限的全部數據
從數據庫中獲取所有數據,遍歷取出的數據從數據權限模型中獲取相應的擁有數據操作權限的權限擁有者,如果該數據未配置數據操作權限的控制,那麽就無需對該數據進行權限級的判斷,如配置了,則需判斷當前用戶是否在該數據操作權限所對應的擁有者中,如用戶不在,則需遞規獲取該數據的父數據的操作權限的擁有者,到用戶擁有權限或遞規結束時終止。
n 分頁獲取操作主體具有數據操作權限的數據
分頁的做法和上面差不多,只是在獲取了所有的數據後在內存中做分頁返回。
1.2.3. 優缺點分析
從上面的基於RBAC的實現方案中可以看出基於RBAC模型的優點在於:
l 易用和高效的授權方式
用戶在進行授權時只需對角色進行授權,之後將相應的角色分配給用戶即可。
l 簡便和高效的授權模型維護
在技術角度來講,進行授權模型的維護上因為基本只需要維護關聯模型而顯得簡單而高效。
缺點在於:
l 復雜的權限校驗
在進行權限校驗時需要不斷的遍歷和遞規,造成了性能的影響。
l 對於數據權限的不夠支持
沒有明確的數據權限模型,可以看到在經過重構的數據權限模型其實已經和RBAC模型有一定的
出入,而且在數據權限的校驗上實現起來是非常的低效。
最終根據說明,設計如下系統架構圖:
一、設計規則定義
1. 數據庫表明定義規則:t_ 模塊名_表名
二、權限管理系統系統設計
1. 用戶管理(t_sys_userInfo)
數據項 |
字段名稱 |
數據定義 |
必輸項 |
檢查規則 |
userId |
用戶ID |
Varchar(20) |
系統產生(UUID) |
單表唯一 |
userName |
用戶名稱 |
Varchar(8) |
手工輸入 |
不可為空 |
userAccount |
用戶帳戶 |
Varchar(20) |
手工輸入 |
全系統唯一 |
userMobile |
移動電話 |
Varchar(11) |
可以為空 |
|
isAdmin |
管理員標誌 |
DECIMAL(1,0) |
系統產生 |
1、超級管理員2、企業管理員3用戶 |
lockFlag |
帳號鎖定標誌 |
DECIMAL(1,0) |
系統產生 |
是否鎖定 1、鎖住 0、未鎖住 鎖定後的用戶不能登錄系統 |
departId
|
所屬部門ID |
Varchar(20) |
手動選擇 |
來源t_sys_org表(orgId) |
departName |
部門名稱 |
Varchar(30) |
系統產生 |
|
orgId |
企業ID |
Varchar(20) |
系統產生 |
來源t_sys_org表(orgId) |
orgName |
企業名稱 |
Varchar(30) |
系統產生 |
來源t_sys_org表(orgName) |
createBy |
創建人ID |
Varchar(20) |
系統產生 |
|
createName |
創建人名稱 |
Varchar(30) |
系統產生 |
|
createTime |
創建時間 |
DATETIME
|
系統產生 |
|
updateBy
|
更新人ID |
Varchar(20) |
系統產生 |
|
updateName |
更新人名稱 |
Varchar(30) |
系統產生 |
|
lastUpdateTime |
更新時間 |
DATETIME |
系統產生 |
|
|
|
|
|
|
CREATE TABLE `t_sys_userInfo` (
`userId` VARCHAR(20) NOT NULL COMMENT ‘用戶主鍵‘,
`userName` VARCHAR(20) NOT NULL,
`orgId` VARCHAR(20) NOT NULL COMMENT ‘所屬機構ID‘,
`orgName` VARCHAR(50) NOT NULL COMMENT ‘所屬機構名稱‘,
`orgPath` VARCHAR(120) NOT NULL COMMENT ‘所屬機構路徑‘,
`userAccount` VARCHAR(16) NOT NULL COMMENT ‘登錄帳號‘,
`userPwd` VARCHAR(16) NOT NULL COMMENT ‘登錄密碼‘,
`userMobile` VARCHAR(11) NULL DEFAULT NULL COMMENT ‘移動電話‘,
`isAdmin` DECIMAL(1,0) NOT NULL DEFAULT ‘3‘ COMMENT ‘1、超級管理員2、企業管理員3用戶‘,
`lockFlag` DECIMAL(1,0) NOT NULL COMMENT ‘是否鎖住 1、鎖住 0、未鎖住‘,
`departId` VARCHAR(20) NOT NULL COMMENT ‘所屬部門‘,
`createBy` VARCHAR(20) NOT NULL,
`createName` VARCHAR(50) NOT NULL COMMENT ‘創建人‘,
`createTime` DATETIME NOT NULL COMMENT ‘創建時間‘,
`lastUpdateBy` VARCHAR(32) NOT NULL COMMENT ‘最後修改人ID‘,
`updateName` VARCHAR(50) NOT NULL COMMENT ‘最後修改人‘,
`lastUpdateTime` DATETIME NOT NULL COMMENT ‘最後修改時間‘,
PRIMARY KEY (`userId`)
)
COMMENT=‘用戶信息表‘
COLLATE=‘utf8_general_ci‘
ENGINE=InnoDB
;
2. 資源管理(t_sys_resInfo)
數據項 |
字段名稱 |
數據定義 |
必輸項 |
檢查規則 |
resId |
用戶ID |
Varchar(20) |
系統產生(UUID) |
單表唯一 |
resName |
用戶名稱 |
Varchar(20) |
手工輸入 |
不可為空 |
parentId |
用戶帳戶 |
Varchar(20) |
手工輸入 |
來源t_sys_resInfo表(resId) |
parentName |
移動電話 |
Varchar(20) |
可以為空 |
來源t_sys_resInfo表(resName) |
resType |
資源類型 |
DECIMAL(1,0) |
手動選擇 |
1、目錄2、菜單 3.操作權限 檢查規則: 1、目錄下面,不能添加操作權限 2、菜單下面不能添加目錄 3、以此類推
|
resState |
資源狀態 |
DECIMAL(1,0) |
手動選擇 |
0,不可用 1可用 |
resSort |
資源排序字段 |
DECIMAL(1,0) |
系統產生 |
來源t_sys_org表(orgId) |
resUrl |
資源訪問地址 |
Varchar(30) |
手動輸入 |
後期自動產生 |
leafCount |
子級菜單數量 |
DECIMAL(1,0) |
系統產生 |
|
resPath |
企業名稱 |
Varchar(30) |
系統產生 |
來源t_sys_org表(orgName) |
iconCls |
創建人ID |
Varchar(32) |
系統產生 |
|
CREATE TABLE `t_sys_resInfo` (
`resId` VARCHAR(32) NOT NULL COMMENT ‘主鍵ID‘,
`resName` VARCHAR(128) NOT NULL COMMENT ‘資源名稱‘,
`parentId` VARCHAR(32) NOT NULL COMMENT ‘資源父節點‘,
`parentName` VARCHAR(128) NOT NULL COMMENT ‘資源父節點名稱‘,
`resType` DECIMAL(1,0) NULL DEFAULT ‘1‘ COMMENT ‘1、功能菜單 2、功能點 3、按鈕‘,
`resState` DECIMAL(1,0) NULL DEFAULT ‘1‘ COMMENT ‘記錄資源的狀態(可用,不可用):0表示不可用,1表示可用‘,
`resSort` DECIMAL(8,0) NULL DEFAULT ‘0‘ COMMENT ‘資源排序 ‘,
`resUrl` VARCHAR(512) NULL DEFAULT ‘‘ COMMENT ‘資源URL地址‘,
`leafCount` DECIMAL(1,0) NULL DEFAULT ‘0‘ COMMENT ‘子節點數量‘,
`resPath` VARCHAR(2048) NULL DEFAULT ‘‘ COMMENT ‘記錄資源節點的路徑:當前菜單的上級菜單,上級菜單的父級菜單‘,
`iconCls` VARCHAR(20) NULL DEFAULT ‘‘ COMMENT ‘資源圖標‘,
PRIMARY KEY (`resId`)
)
COMMENT=‘系統資源‘
COLLATE=‘utf8_general_ci‘
ENGINE=InnoDB
;
3. 組織機構表(t_sys_org)
CREATE TABLE `t_sys_org` (
`orgId` VARCHAR(20) NOT NULL COMMENT ‘組織主鍵‘,
`orgName` VARCHAR(50) NOT NULL COMMENT ‘組織名稱‘,
`orgShortName` VARCHAR(30) NULL DEFAULT NULL COMMENT ‘組織簡稱‘,
`parentId` VARCHAR(32) NOT NULL COMMENT ‘組織父節點ID‘,
`parentName` VARCHAR(50) NOT NULL COMMENT ‘父節點編碼‘,
`orgType` DECIMAL(1,0) NOT NULL DEFAULT ‘1‘ COMMENT ‘組織的類型 1、企業 2、部門 3、分公司,4,支行‘,
`orgStatus` DECIMAL(1,0) NOT NULL DEFAULT ‘1‘ COMMENT ‘記錄組織的狀態是否啟用:0,停用/1,啟用‘,
`orgHisStatus` DECIMAL(1,0) NOT NULL DEFAULT ‘1‘ COMMENT ‘0,停用/1,啟用‘,
`orgLinkMan` VARCHAR(50) NULL DEFAULT NULL COMMENT ‘機構的法人代表名稱‘,
`orgTelephone` VARCHAR(20) NULL DEFAULT NULL COMMENT ‘機構的聯系電話‘,
`orgFax` VARCHAR(20) NULL DEFAULT NULL COMMENT ‘機構的傳真‘,
`orgEmail` VARCHAR(100) NULL DEFAULT NULL COMMENT ‘機構的電子郵箱‘,
`orgAddress` VARCHAR(200) NULL DEFAULT NULL COMMENT ‘組織地址‘,
`orgWebsite` VARCHAR(200) NULL DEFAULT NULL COMMENT ‘組織的網站‘,
`leafCount` DECIMAL(1,0) NULL DEFAULT NULL COMMENT ‘子企業數量‘,
`orgSort` DECIMAL(10,0) NULL DEFAULT NULL COMMENT ‘組織排序‘,
`resIconStyle` VARCHAR(20) NULL DEFAULT ‘‘ COMMENT ‘資源圖標‘,
`orgPath` VARCHAR(2048) NULL DEFAULT NULL COMMENT ‘記錄組織的節點路徑‘,
`createBy` VARCHAR(20) NULL DEFAULT NULL COMMENT ‘創建人ID‘,
`createName` VARCHAR(50) NULL DEFAULT NULL COMMENT ‘創建人‘,
`createTime` DATETIME NULL DEFAULT NULL COMMENT ‘創建時間‘,
`lastUpdateBy` VARCHAR(20) NULL DEFAULT NULL COMMENT ‘最後修改人ID‘,
`updateName` VARCHAR(50) NULL DEFAULT NULL COMMENT ‘最後修改人‘,
`lastUpdateTime` DATETIME NULL DEFAULT NULL COMMENT ‘最後修改時間‘,
PRIMARY KEY (`orgId`)
)
COMMENT=‘組織架構信息‘
COLLATE=‘utf8_general_ci‘
ENGINE=InnoDB
;
4. 組織角色表(t_sys_role)
CREATE TABLE `t_sys_role` (
`roleId` VARCHAR(20) NOT NULL COMMENT ‘角色表主鍵ID‘,
`orgId` VARCHAR(20) NULL DEFAULT NULL COMMENT ‘所屬組織‘,
`orgPath` VARCHAR(20) NULL DEFAULT NULL COMMENT ‘組織路徑‘,
`orgName` VARCHAR(50) NOT NULL COMMENT ‘組織名稱‘,
`roleName` VARCHAR(50) NOT NULL COMMENT ‘角色名稱‘,
`roleDesc` VARCHAR(100) NULL DEFAULT NULL COMMENT ‘角色描述‘,
`createBy` VARCHAR(20) NOT NULL COMMENT ‘創建人ID‘,
`createName` VARCHAR(50) NOT NULL COMMENT ‘創建人‘,
`createTime` DATETIME NOT NULL COMMENT ‘創建時間‘,
`lastUpdateBy` VARCHAR(20) NULL DEFAULT NULL COMMENT ‘最後修改人ID‘,
`updateName` VARCHAR(50) NULL DEFAULT NULL COMMENT ‘最後修改人‘,
`lastUpdateTime` DATETIME NULL DEFAULT NULL COMMENT ‘最後修改時間‘,
PRIMARY KEY (`roleId`)
)
COMMENT=‘角色信息表‘
COLLATE=‘utf8_general_ci‘
ENGINE=InnoDB
;
5. 用戶角色表(t_sys_userRole)
CREATE TABLE `t_sys_userRole` (
`userRoleId` VARCHAR(20) NOT NULL COMMENT ‘主鍵ID‘,
`roleId` VARCHAR(20) NULL DEFAULT NULL COMMENT ‘角色表主鍵ID‘,
`userId` VARCHAR(20) NULL DEFAULT NULL COMMENT ‘用戶主鍵‘,
PRIMARY KEY (`userRoleId`)
)
COMMENT=‘用戶角色關系表‘
COLLATE=‘utf8_general_ci‘
ENGINE=InnoDB;
6. 角色資源表(t_sys_roleRes)
CREATE TABLE `t_sys_roleRes` (
`roleResId` VARCHAR(20) NOT NULL COMMENT ‘角色資源主鍵ID‘,
`roleId` VARCHAR(22) NOT NULL COMMENT ‘角色表主鍵ID‘,
`resId` VARCHAR(20) NOT NULL COMMENT ‘資源主鍵‘,
`isReadWrite` DECIMAL(1,0) NOT NULL DEFAULT 1 COMMENT ‘1,只讀取2,可讀寫‘,
PRIMARY KEY (`roleResId`)
)
COMMENT=‘角色資源關系表‘
COLLATE=‘utf8_general_ci‘
ENGINE=InnoDB
7. 企業資源表(t_sys_orgRes)
CREATE TABLE `t_sys_orgRes` (
`orgResId` VARCHAR(20) NOT NULL COMMENT ‘角色資源主鍵ID‘,
`orgId` VARCHAR(22) NOT NULL COMMENT ‘角色表主鍵ID‘,
`resId` VARCHAR(20) NOT NULL COMMENT ‘資源主鍵‘,
`isReadWrite` DECIMAL(1,0) NOT NULL DEFAULT 1 COMMENT ‘1,只讀取2,可讀寫‘,
PRIMARY KEY (`orgResId`)
)
COMMENT=‘角色資源關系表‘
COLLATE=‘utf8_general_ci‘
ENGINE=InnoDB
相關運營截圖:
轉載自-- https://www.cnblogs.com/jurendage/p/9120168.html
26、生鮮電商平臺-RBAC系統權限的設計與架構