但凡涉及多用戶(hù)不同權限的網(wǎng)絡(luò )或者單機程序,都會(huì )有權限管理的問(wèn)題,比較突出的是MIS系統。
下面我要說(shuō)的是MIS系統權限管理的數據庫設計及實(shí)現,當然,這些思路也可以推廣開(kāi)來(lái)應用,比如說(shuō)在BBS中用來(lái)管理不同級別的用戶(hù)權限。
權限設計通常包括數據庫設計、應用程序接口(API)設計、程序實(shí)現三個(gè)部分。
這三個(gè)部分相互依存,密不可分,要實(shí)現完善的權限管理體系,必須考慮到每一個(gè)環(huán)節可行性與復雜程度甚至執行效率。
我們將權限分類(lèi),首先是針對數據存取的權限,通常有錄入、瀏覽、修改、刪除四種,其次是功能,它可以包括例如統計等所有非直接數據存取操作,另外,我們還可能對一些關(guān)鍵數據表某些字段的存取進(jìn)行限制。除此,我想不出還有另外種類(lèi)的權限類(lèi)別。
完善的權限設計應該具有充分的可擴展性,也就是說(shuō),系統增加了新的其它功能不應該對整個(gè)權限管理體系帶來(lái)較大的變化,要達到這個(gè)目的,首先是數據庫設計合理,其次是應用程序接口規范。
我們先討論數據庫設計。通常我們使用關(guān)系數據庫,這里不討論基于Lotus產(chǎn)品的權限管理。
權限表及相關(guān)內容大體可以用六個(gè)表來(lái)描述,如下:
1 角色(即用戶(hù)組)表:包括三個(gè)字段,ID,角色名,對該角色的描述;
2 用戶(hù)表:包括三個(gè)或以上字段,ID,用戶(hù)名,對該用戶(hù)的描述,其它(如地址、電話(huà)等信息);
3 角色-用戶(hù)對應表:該表記錄用戶(hù)與角色之間的對應關(guān)系,一個(gè)用戶(hù)可以隸屬于多個(gè)角色,一個(gè)角色組也可擁有多個(gè)用戶(hù)。包括三個(gè)字段,ID,角色ID,用戶(hù)ID;
4 限制內容列表:該表記錄所有需要加以權限區分限制的數據表、功能和字段等內容及其描述,包括三個(gè)字段,ID,名稱(chēng),描述;
5 權限列表:該表記錄所有要加以控制的權限,如錄入、修改、刪除、執行等,也包括三個(gè)字段,ID,名稱(chēng),描述;
6 權限-角色-用戶(hù)對應表:一般情況下,我們對角色/用戶(hù)所擁有的權限做如下規定,角色擁有明令允許的權限,其它一律禁止,用戶(hù)繼承所屬角色的全部權限,在 此范圍內的權限除明令禁止外全部允許,范圍外權限除明令允許外全部禁止。該表的設計是權限管理的重點(diǎn),設計的思路也很多,可以說(shuō)各有千秋,不能生搬硬套說(shuō) 某種方法好。對此,我的看法是就個(gè)人情況,找自己覺(jué)得合適能解決問(wèn)題的用。
先說(shuō)第一種也是最容易理解的方法,設計五個(gè)字段:ID,限制內容ID,權限ID,角色/用戶(hù)類(lèi)型(布爾型字段,用來(lái)描述一條記錄記錄的是角色權限還是用戶(hù)權限),角色/用戶(hù)ID,權限類(lèi)型(布爾型字段,用來(lái)描述一條記錄表示允許還是禁止)
好了,有這六個(gè)表,根據表六,我們就可以知道某個(gè)角色/用戶(hù)到底擁有/禁止某種權限。
或者說(shuō),這么設計已經(jīng)足夠了,我們完全實(shí)現了所需要的功能:可以對角色和用戶(hù)分別進(jìn)行權限定制,也具有相當的可擴展性,比如說(shuō)增加了新功能,我們只 需要添加一條或者幾條記錄就可以,同時(shí)應用程序接口也無(wú)須改動(dòng),具有相當的可行性。但是,在程序實(shí)現的過(guò)程中,我們發(fā)現,使用這種方法并不是十分科學(xué),例 如瀏覽某個(gè)用戶(hù)所擁有的權限時(shí),需要對數據庫進(jìn)行多次(甚至是遞歸)查詢(xún),極不方便。于是我們需要想其它的辦法。使用過(guò)Unix系統的人們都知道, Unix文件系統將對文件的操作權限分為三種:讀、寫(xiě)和執行,分別用1、2、4三個(gè)代碼標識,對用戶(hù)同時(shí)具有讀寫(xiě)權限的文件被記錄為3,即1+2。我們也 可以用類(lèi)似的辦法來(lái)解決這個(gè)問(wèn)題。初步的想法是修改權限列表,加入一個(gè)字段:標識碼,例如,我們可以將錄入權限標識為1,瀏覽權限標識為2,修改權限標識 為4,刪除權限標識為8,執行權限標識為16,這樣,我們通過(guò)權限累加的辦法就可以輕易的將原本要分為幾條記錄描述的權限放在一起了,例如,假定某用戶(hù) ID為1,庫存表對應的限制內容ID為2,同時(shí)規定角色類(lèi)型為0、用戶(hù)類(lèi)型為1,我們就可以將該用戶(hù)具有錄入、瀏覽、修改、刪除庫存表的權限描述為: 2,15,1,1。
確實(shí)很簡(jiǎn)單,不是嗎?甚至還有更過(guò)激的辦法,將限制內容列表也加上一列,定義好標識碼,這樣,我們甚至可以用簡(jiǎn)單的一條記錄描述某個(gè)用戶(hù)具有的對全 部?jì)热菟哂械娜繖嘞蘖?。當然,這樣做的前提是限制內容數量比較小,不然,呵呵,2的n次方遞增起來(lái)可是數量驚人,不容易解析的。
從表面上看,上述方法足以達到實(shí)現功能、簡(jiǎn)化數據庫設計及實(shí)現的復雜度這個(gè)目的,但這樣做有個(gè)弊端,我們所涉及的權限列表不是相互獨立而是互相依賴(lài) 的,比如說(shuō)修改權限,其實(shí)是包含瀏覽權限的,例如,我們可能只是簡(jiǎn)單的設置用戶(hù)對庫存表存取的權限值為錄入+修改+刪除(1+4+8=13),但事實(shí)上, 該用戶(hù)具有(1+2+4+8=15)的權限,也就是說(shuō),在這種方案中,13=15。于是當我們調用API詢(xún)問(wèn)某用戶(hù)是否具有瀏覽權限時(shí),就必須判斷該用戶(hù) 是否具有對該數據表的修改權限,因此,如果不能在程序中固化權限之間的包含關(guān)系,就不能利用應用程序接口簡(jiǎn)單的做出判斷。但這與我們的目的“充分的可擴展 性”矛盾。
這個(gè)問(wèn)題如何解決?我想到了另外一種設置標識碼的方法,那就是利用素數。我們不妨將錄入、瀏覽、修改、刪除、執行的基本標志碼定為 2,3,5,7,11,當遇到權限互相包含的時(shí)候,我們將它的標識碼設定為兩個(gè)(或多個(gè))基本標志碼的乘積,例如,可以將“修改”功能的標志碼定為3*5 =15,然后將所有的權限相乘,就得到了我們需要的最終權限標識值。這樣,我們在詢(xún)問(wèn)用戶(hù)是否具有某項權限的時(shí)候,只需要將最終的值分解成質(zhì)因子,例如, 我們可以定義一個(gè)用戶(hù)具有錄入+修改+刪除庫存表的權限為 2*15*7=2*3*5*7,即表示,該用戶(hù)具有了對庫存表錄入+瀏覽+修改+刪除權限。
當然,對權限列表我們使用上述方法的前提是權限列表記錄條數不會(huì )太多并且關(guān)系不是十分復雜,否則,光是解析權限代碼就要機器忽悠半宿:)
我希望以上的分析是正確且有效的(事實(shí)上,我也用這些的方法在不止一套系統中實(shí)現),但無(wú)論如何,我覺(jué)得如此實(shí)現權限管理,只是考慮了數據庫設計和 應用程序接口兩部分內容,對于實(shí)現,還是顯得很費勁。因此,我懇請有過(guò)類(lèi)似設計、實(shí)現經(jīng)驗的同志們提出建設性的意見(jiàn)和修改建議。
另外,關(guān)于數據庫設計的思路還有使用二維表的,這將在以后的時(shí)間里討論,關(guān)于應用程序接口的設計和實(shí)現我也將在利用另外篇幅和大家共同探討,代碼將用類(lèi)C語(yǔ)法實(shí)現(我不喜歡pascal,抱歉)
歡迎朋友們和我聯(lián)系,mailto:berg@91search.com,也歡迎訪(fǎng)問(wèn)我和另外一位朋友共同建設的網(wǎng)站:
http://www.91search.com,那里將有一個(gè)音樂(lè )搜索的工具軟件提供下載。
========================================
關(guān)于權限包容關(guān)系通過(guò)角色和權限掩碼來(lái)實(shí)現。
/// <summary>
/// 權限保護類(lèi)型枚舉類(lèi)型。
/// </summary>
public enum ProtectEnum
{
/// <summary>撤回權限保護類(lèi)型</summary>
RevokeProtect = 0,
/// <summary>授予權限保護類(lèi)型</summary>
GrantProtect = 1,
/// <summary>拒絕權限保護類(lèi)型</summary>
DenyProtect = 2
}
/// <summary>
/// 系統固定用戶(hù)或角色枚舉類(lèi)型。
/// </summary>
/// <remarks>
/// 管理員角色:16399 = 100000000001111
/// 所有者角色:16385 = 100000000000001
/// 只讀者角色:16386 = 100000000000010
/// 安全員角色:16388 = 100000000000100
/// 配置員角色:16392 = 100000000001000
/// </remarks>
public enum FixedRoleEnum
{
///<summary>系統管理員固定用戶(hù)</summary>
Administrator = 1,
///<summary>系統管理員固定角色</summary>
Administrators = 16399,
///<summary>所有者固定角色(具有讀寫(xiě)操作之權限)</summary>
Authors = 16385,
///<summary>只讀者固定角色(具有只讀操作之權限)</summary>
Readers = 16386,
///<summary>系統安全管理員固定角色</summary>
Security = 16388,
///<summary>系統設置管理員固定角色</summary>
Setting = 16392
}
/// <summary>
/// 系統權限枚舉類(lèi)型。
/// </summary>
public enum PermissionEnum
{
/// <summary>“讀取”權限</summary>
FetchPermission = 1,
/// <summary>“新增”權限</summary>
AddNewPermission = 2,
/// <summary>“更新”權限</summary>
UpdatePermission = 4,
/// <summary>“刪除”權限</summary>
DeletePermission = 8,
/// <summary>“打印”權限</summary>
PrintPermission = 16,
/// <summary>系統保留,應用于流程處理</summary>
FlowPermission = 1024,
/// <summary>系統保留,應用于流程處理</summary>
VoidPermission = 2048
}
如果用戶(hù)“Popeye”對“銷(xiāo)售出倉單[2009]”系統對象具有讀寫(xiě)(讀?。薷模珓h除+新增)權限:(權限表定義如下TPermission)
FormID UID Permission
======= ==== ==========
2009 Popeye 1+2+4+8=15
***** 上面系統定義的默認權限肯定是不夠系統使用的,那么還有一些權限(例如:報關(guān)系統中的“計算差異表”“制造申報單”等權限,就由系統再定義),其實(shí)不用太 擔心會(huì )不夠用的,因為在一個(gè)Form中不可能會(huì )出現所有權限情況,所以,系統自定義的權限掩碼可重復使用在不同的表單中。*****
建議不要把角色和用戶(hù)分開(kāi)兩張表來(lái)存儲(可參考MS-SQL Server中的sys_users表),因為在后面的權限定義表需要引用這個(gè)表的UID(其可為用戶(hù)或角色,SQL中是使用UID的數值范圍來(lái)區別用戶(hù) 與角色的,建議也如此。),版主說(shuō)的角色與用戶(hù)分開(kāi)對待權限設置,這點(diǎn)我不贊成。因為角色只不過(guò)是一種用戶(hù)組,其應該享用用戶(hù)的權限定義范圍,在其下屬的 角色成員(注意角色成員不同于用戶(hù)或角色哦,其可以為角色也可以為用戶(hù))均默認繼承其定義的權限,除非角色成員重新指派其上級角色定義的權限字。下面給出 我的相關(guān)表定義:
TUser(用戶(hù)或角色表)
===================
(PK)UID int NOT NULL(主鍵)
Name nvarchar(50) NOT NULL(唯一性約束)
FullName nvarchar(100) NULL
Description nvarchar(255) NULL
MasterNo varchar(25) NULL(注:該字段對應為員工表中的員工編號,通過(guò)該字段就可以關(guān)聯(lián)知道該用戶(hù)或角色所屬的員工了,在企業(yè)管理系統中很有用?。。?br>TMember(用戶(hù)與角色關(guān)系表)
=========================
(*PK)RoleID int NOT NULL
(*PK)UserID int NOT NULL
TPermission(用戶(hù)權限表)
=======================
(*PK)FormID int NOT NULL(表示系統中各個(gè)模塊或表單的唯一編號)
(*PK)UserID int NOT NULL(用戶(hù)或角色編號)
Protect bit NOT NULL(1:表示顯示授予權限;0:表示顯示拒絕權限)
Permission int NOT NULL(權限掩碼和)
***** 如果哪位兄弟有意研究權限與流程定制方面的東東,相信找偶是沒(méi)錯的了?。?!呵呵~~~ 老板,給分啊~~~~~×××××
==========================================
以上的方法與我做的項目的方法基本一致,現摘一部分的表結構,以供大家參考
create table t_workelement /*工作元素表*/
(
code varchar(20) not null, /*元素的代碼,唯一*/
name varchar(50) not null UNIQUE,/*元素的名稱(chēng),唯一*/
type int not null, /*類(lèi)型 0-單據操作 1-報表操作 2-功能操作*/
bcode varchar(20) null, /*對應操作的單據\報表\功能的代碼*/
style int null, /*單據:類(lèi)型 0-查看 1-新增 2-修改 3-刪除*/
/*報表:無(wú)*/
/*功能:無(wú)*/
term ntext null, /*單據:查看\修改\刪除時(shí)要符合的條件,如"{$承攬合同.編號}=12\n{$承攬合同.名稱(chēng)}<>‘a(chǎn)fd‘"*/
primary key(code)
)
go
drop table t_role
go
create table t_role /*角色表*/
(
name varchar(30) not null,
category varchar(50) null,
remark varchar(100) null,
primary key(name)
)
go
drop table t_roleelement
go
create table t_roleelement /*角色元素操作表*/
(
rname varchar(30) not null, /*角色名稱(chēng)*/
ecode varchar(20) not null, /*元素的代碼*/
primary key(rname,ecode)
)
go
drop table t_users
go
create table t_users /*用戶(hù)表*/
(
name varchar(20) not null, /*用戶(hù)的名稱(chēng)*/
dcode varchar(20) not null, /*所屬的部門(mén)*/
category varchar(50) null, /*用戶(hù)的類(lèi)別*/
pswd varchar(15) null, /*密碼*/
primary key(name)
)
go
/*插入系統管理員*/
INSERT INTO t_users
(
name,
dcode,
category,
pswd
)
VALUES
(
‘Admini‘,
‘system‘,
‘超級用戶(hù)‘,
‘‘
)
go
drop table t_userrole
go
create table t_userrole /*用戶(hù)角色表*/
(
uname varchar(20) not null, /*用戶(hù)名稱(chēng)*/
rname varchar(30) not null, /*角色的名稱(chēng)*/
primary key(uname,rname)
)
go
INSERT INTO t_userrole
(
uname,
rname
)
VALUES
(
‘Admini‘,
‘系統管理員‘
)
go
drop table t_dept
go
create table t_dept /*部門(mén)表*/
(
code varchar(20) not null, /*部門(mén)的代碼*/
name varchar(50) not null UNIQUE,/*部門(mén)的名稱(chēng)*/
type varchar(10) null, /*部門(mén)的類(lèi)別 行政 倉庫 車(chē)間*/
subtype varchar(16) null, /*子類(lèi)別 成品倉庫 原料倉庫自定義*/
primary key(code)
)
go
/*插入系統管理部*/
INSERT INTO t_dept
(
code,
name,
type
)
VALUES
(
‘system‘,
‘系統管理部‘,
‘行政‘
)
go
續:關(guān)于權限系統的設計
jackyz Dec 7, 2002 1:00 AM
source:
http://www.jdon.com/jive/article.jsp?forum=46&thread=4110&message=438816Note:
首先,向版主致歉。這原是關(guān)于權限系統設計問(wèn)題的回帖,本不應該另開(kāi)新貼。而在下的另開(kāi)新貼,一方面是因為本人的觀(guān)點(diǎn)中與很多人 的觀(guān)點(diǎn)差別較大,另一方面也擔心其會(huì )被“埋沒(méi)”在原貼的大量回帖中。此外,本貼的內容整理與編排耗費了我周末接近一整個(gè)晚上的時(shí)間,包含了我對近期項目中 權限系統的思考與總結,希望引來(lái)大家足夠的目光和指導。請版主體諒。
權限系統,其重要性當然不言自明??匆?jiàn)大家的方案,有相當多優(yōu)秀的創(chuàng )意與經(jīng)驗,我的項目也有所涉及,以下說(shuō)明的是我最近在一個(gè)企業(yè) EJB 項目中初步實(shí)現的方案(以及設計考量),望與諸位共商榷。
前言:
權限往往是一個(gè)極其復雜的問(wèn)題,但也可簡(jiǎn)單表述為這樣的邏輯表達式:判斷“who 對 what(which) 進(jìn)行 how 的操作”的邏輯表達式是否為真。
針對不同的應用,需要根據項目的實(shí)際情況和具體架構,在維護性、靈活性、完整性等N多個(gè)方案之間比較權衡,選擇符合的方案。
目標:
這個(gè)權限系統的設計,我主要考慮了這么幾個(gè)目標:
直觀(guān),因為系統最終會(huì )由最終用戶(hù)來(lái)維護,權限分配的直觀(guān)和容易理解,顯得比較重要,系統不辭勞苦的實(shí)現了組的繼承,除了功能的必須,更主要的就是因為它足夠直觀(guān)。
簡(jiǎn) 單,包括概念數量上的簡(jiǎn)單和意義上的簡(jiǎn)單還有功能上的簡(jiǎn)單。想用一個(gè)權限系統解決所有的權限問(wèn)題是不現實(shí)的。設計中將常常變化的“定制”特點(diǎn)比較強的部分 判斷為業(yè)務(wù)邏輯,而將常常相同的“通用”特點(diǎn)比較強的部分判斷為權限邏輯就是基于這樣的思路。此外,同時(shí)具備 Role 和 Group 的系統難于理解,權衡之下,摒棄了 Role 概念。
擴展,我在以前的項目中也實(shí)現過(guò)基于 Role 概念的權限系統,但效果不太理想。之所以在這里摒棄 Role 的概念,另一個(gè)原因就是因為它不易擴展。通常 Role 的設計方式意味著(zhù)預先已經(jīng)定好了一組權限,這樣的“預先設計”,常常會(huì )鼓勵程序員 hardcode 這些權限相關(guān)的部分,而,如果這么做的話(huà),當需要重新定義 Role 時(shí),擴展就會(huì )變得極為困難。而采用可繼承的 Group 概念在支持權限以組方式定義的同時(shí)有效避免了重定義時(shí)在擴展上的困難。
名詞:
下面兩個(gè)名詞極其重要,是整個(gè)設計問(wèn)題邊界定義的關(guān)鍵,或許我的理解與通常的理解不同,在此有必要特別澄清。
粗粒度:表示類(lèi)別級,即,僅考慮對象的類(lèi)別,不考慮對象的某個(gè)特定實(shí)例。比方,用戶(hù)管理中,創(chuàng )建、刪除,對所有的用戶(hù)都一視同仁,并不區分操作的具體對象實(shí)例。
細粒度:表示實(shí)例級,即,需要考慮具體對象的實(shí)例,當然,細粒度是在考慮粗粒度的對象類(lèi)別之后才再考慮特定實(shí)例。比方,合同管理中,列表、刪除,需要區分該合同實(shí)例是否為當前用戶(hù)所創(chuàng )建。
原則:
權 限邏輯配合業(yè)務(wù)邏輯。即,權限系統以為業(yè)務(wù)邏輯提供服務(wù)為目標。純粹紙面意義的極其復雜和精巧的權限系統,這里不作討論。相當多細粒度的權限問(wèn)題因其極其 獨特而不具通用意義,它們也能被理解為是“業(yè)務(wù)邏輯”的一部分。比方,要求:“合同資源只能被它的創(chuàng )建者刪除,與創(chuàng )建者同組的用戶(hù)可以修改,所有的用戶(hù)能 夠瀏覽”。這既可以認為是一個(gè)細粒度的權限問(wèn)題,也可以認為是一個(gè)業(yè)務(wù)邏輯問(wèn)題。在這里我認為它是業(yè)務(wù)邏輯問(wèn)題,在整個(gè)權限系統的架構設計之中不予過(guò)多考 慮。當然,權限系統的架構也必須要能支持這樣的控制判斷?;蛘哒f(shuō),系統提供足夠多但不是完全的控制能力。即,設計原則歸結為:“系統只提供粗粒度的權限, 細粒度的權限被認為是業(yè)務(wù)邏輯的職責”。
需要再次強調的是,這里表述的權限系統僅是一個(gè)“不完全”的權限系統,即,它不提供所有關(guān)于權限 的問(wèn)題的解決方法。它提供一個(gè)基礎,并解決那些具有“共性”的(或者說(shuō)粗粒度的)部分。在這個(gè)基礎之上,根據“業(yè)務(wù)邏輯”的獨特權限需求,編碼實(shí)現剩余部 分(或者說(shuō)細粒度的)部分,才算完整?;氐綑嘞薜膯?wèn)題公式,我的設計僅解決了 who + what + how 的問(wèn)題,which 的權限問(wèn)題留給業(yè)務(wù)邏輯解決。
概念:
User:用戶(hù)。解決 who 的問(wèn)題。
Group:組。權限分配的單位與載體。權限不考慮分配給特定的用戶(hù)。組可以包括組(以實(shí)現權限的繼承)。
Operate:操作。表明對 what 的 how 操作。
說(shuō)明:
User
與大家的都一樣,沒(méi)什么好說(shuō)的。
Group
與 大家的類(lèi)似,所不同的是,Group 要實(shí)現繼承。即,在創(chuàng )建時(shí)必須要指定該 Group 的 Parent 是什么 Group 。在粗粒度控制上,可以認為,只要某用戶(hù)直接或者間接的屬于某個(gè) Group 那么它就具備這個(gè) Group 的所有操作許可。細粒度控制上,在業(yè)務(wù)邏輯的判斷中,User 僅應關(guān)注其直接屬于的 Group ,用來(lái)判斷是否“同組”,間接的 Group 對權限的控制意義不大,試設想存在一個(gè) All User 的 Group 是所有 Group 的祖先,這樣的情形下,判斷的結果不具備實(shí)際意義。
User 與 Group 是多對多的關(guān)系。即,一個(gè) User 可以屬于多個(gè) Group 之中,一個(gè) Group 可以包括多個(gè) User 。
子 Group 與 父 Group 是多對一的關(guān)系。即,一個(gè)子 Group 只能有一個(gè)父 Group ,一個(gè)父 Group 可以包括多個(gè)子 Group 。
Operate
某種意義上類(lèi)似于大家的 Resource + Privilege 概念,但,這里的 Resource 僅包括 Resource Type 不表示 Resource Instance。Operate 概念上與大家的觀(guān)點(diǎn)區別比較,后面有詳細的解釋。
Group 與 Operate 是多對多的關(guān)系。
各概念的關(guān)系圖示如下:
User
|*
|
|* 1
Group---+
|* |* |
| +---+
|*
Operate
解釋?zhuān)?br>
Operate 的定義包括了 Resource Type 和 Method 概念。即, what 和 how 的概念。之所以將 what 和 how 綁定在一起作為一個(gè) Operate 概念而不是分開(kāi)建模再建立關(guān)聯(lián),這是因為很多的 how 對于某 what 才有意義。比方,發(fā)布操作對新聞對象才有意義,對用戶(hù)對象則沒(méi)有意義。
how 本身的意義也有所不同,這里并非僅定義類(lèi) UNIX 的 RWX 三種操作,這樣的定義對于文件系統是合理的,但,對于其他的應用領(lǐng)域或許就不是那么足夠了。具體來(lái)說(shuō),對于每一個(gè) what 可以定義 N 種操作。比方,對于合同這類(lèi)對象,可以定義創(chuàng )建操作、提交操作、檢查沖突操作等??梢哉J為,how 概念對應于每一個(gè)商業(yè)方法。
其中,與 具體用戶(hù)身份相關(guān)的操作既可以定義在操作的業(yè)務(wù)邏輯之中,也可以定義在操作級別。比方,創(chuàng )建者的瀏覽視圖與普通用戶(hù)的瀏覽視圖要求內容不同。你既可以在外 部定義兩個(gè)操作方法,也可以在一個(gè)操作方法的內部根據具體邏輯進(jìn)行處理。具體應用哪一種方式應依據實(shí)際情況進(jìn)行處理。
這樣的架構,應能在易于理解和管理的情況下,滿(mǎn)足絕大部分粗粒度權限控制的功能需要。但是,除了粗粒度權限,無(wú)可否認,系統中必然還會(huì )包括無(wú)數對具體 Instance 的細粒度權限。這些問(wèn)題,被留給業(yè)務(wù)邏輯來(lái)解決,這樣的考慮基于以下兩點(diǎn)。
一 方面,細粒度的權限判斷必須要在資源上建模權限分配的支持信息才可能得以實(shí)現。比方,如果要求創(chuàng )建者和普通用戶(hù)看到不同的信息內容,那么,資源本身應該有 其創(chuàng )建者的信息。如同 Unix 的每一個(gè)文件(資源),都定義了對 Owner, Group, All 的不同操作屬性。
另一方面, 細粒度的權限常常具有相當大的業(yè)務(wù)邏輯相關(guān)性。對不同的業(yè)務(wù)邏輯,常常意味著(zhù)完全不同的權限判定原則和策略。相比之下,粗粒度的權限更具通用性,將其實(shí)現 為一個(gè)架構,更有重用價(jià)值;而將細粒度的權限判斷實(shí)現為一個(gè)架構級別的東西就顯得繁瑣,而且不是那么的有必要,用定制的代碼來(lái)實(shí)現就更簡(jiǎn)潔,更靈活。