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