許可權系統概要(收集,整理)

代文龍發表於2003-06-03
前言:
許可權往往是一個極其複雜的問題,但也可簡單表述為這樣的邏輯表示式:判斷“Who對What(Which)進行How的操作”的邏輯表示式是否為真。針對不同的應用,需要根據專案的實際情況和具體架構,在維護性、靈活性、完整性等N多個方案之間比較權衡,選擇符合的方案。
目標:
直觀,因為系統最終會由終端使用者來維護,許可權分配的直觀和容易理解,顯得比較重要,系統不辭勞苦的實現了組的繼承,除了功能的必須,更主要的就是因為它足夠直觀。
簡單,包括概念數量上的簡單和意義上的簡單還有功能上的簡單。想用一個許可權系統解決所有的許可權問題是不現實的。設計中將常常變化的“定製”特點比較強的部分判斷為業務邏輯,而將常常相同的“通用”特點比較強的部分判斷為許可權邏輯就是基於這樣的思路。
擴充套件,採用可繼承在擴充套件上的困難。的Group概念在支援許可權以組方式定義的同時有效避免了重定義時
現狀:
對於在企業環境中的訪問控制方法,一般有三種:
1.自主型訪問控制方法。目前在我國的大多數的資訊系統中的訪問控制模組中基本是藉助於自主型訪問控制方法中的訪問控制列表(ACLs)。
2.強制型訪問控制方法。用於多層次安全級別的軍事應用。
3.基於角色的訪問控制方法(RBAC)。是目前公認的解決大型企業的統一資源訪問控制的有效方法。其顯著的兩大特徵是:1.減小授權管理的複雜性,降低管理開銷。2.靈活地支援企業的安全策略,並對企業的變化有很大的伸縮性。
名詞:
粗粒度:表示類別級,即僅考慮物件的類別(the type of object),不考慮物件的某個特
定例項。比如,使用者管理中,建立、刪除,對所有的使用者都一視同仁,並不區分操作的具體物件例項。
細粒度:表示例項級,即需要考慮具體物件的例項(the instance of object),當然,細
粒度是在考慮粗粒度的物件類別之後才再考慮特定例項。比如,合同管理中,列表、刪除,需要區分該合同例項是否為當前使用者所建立。
原則:
許可權邏輯配合業務邏輯。即許可權系統以為業務邏輯提供服務為目標。相當多細粒度的許可權問題因其極其獨特而不具通用意義,它們也能被理解為是“業務邏輯”的一部分。比如,要求:“合同資源只能被它的建立者刪除,與建立者同組的使用者可以修改,所有的使用者能夠瀏覽”。這既可以認為是一個細粒度的許可權問題,也可以認為是一個業務邏輯問題。在這裡它是業務邏輯問題,在整個許可權系統的架構設計之中不予過多考慮。當然,許可權系統的架構也必須要能支援這樣的控制判斷。或者說,系統提供足夠多但不是完全的控制能力。即,設計原則歸結為:“系統只提供粗粒度的許可權,細粒度的許可權被認為是業務邏輯的職責”。
需要再次強調的是,這裡表述的許可權系統僅是一個“不完全”的許可權系統,即,它不提供所有關於許可權的問題的解決方法。它提供一個基礎,並解決那些具有“共性”的(或者說粗粒度的)部分。在這個基礎之上,根據“業務邏輯”的獨特許可權需求,編碼實現剩餘部分(或者說細粒度的)部分,才算完整。回到許可權的問題公式,通用的設計僅解決了Who+What+How 的問題,其他的許可權問題留給業務邏輯解決。
概念:
Who:許可權的擁用者或主體(Principal、User、Group、Role、Actor等等)
What:許可權針對的物件或資源(Resource、Class)。
How:具體的許可權(Privilege, 正向授權與負向授權)。
Role:是角色,擁有一定數量的許可權。
Operator:操作。表明對What的How 操作。
說明:
User:與 Role 相關,使用者僅僅是純粹的使用者,許可權是被分離出去了的。User是不能與 Privilege 直接相關的,User 要擁有對某種資源的許可權,必須透過Role去關聯。解決 Who 的問題。
Resource:就是系統的資源,比如部門新聞,文件等各種可以被提供給使用者訪問的物件。資源可以反向包含自身,即樹狀結構,每一個資源節點可以與若干指定許可權類別相關可定義是否將其許可權應用於子節點。
Privilege:是Resource Related的許可權。就是指,這個許可權是繫結在特定的資源例項上的。比如說部門新聞的釋出許可權,叫做"部門新聞釋出許可權"。這就表明,該Privilege是一個釋出許可權,而且是針對部門新聞這種資源的一種釋出許可權。Privilege是由Creator在做開發時就確定的。許可權,包括系統定義許可權和使用者自定義許可權使用者自定義許可權之間可以指定排斥和包含關係(如:讀取,修改,管理三個許可權,管理 許可權 包含 前兩種許可權)。Privilege 如"刪除" 是一個抽象的名詞,當它不與任何具體的 Object 或 Resource 繫結在一起時是沒有任何意義的。拿新聞釋出來說,釋出是一種許可權,但是隻說釋出它是毫無意義的。因為不知道釋出可以操作的物件是什麼。只有當釋出與新聞結合在一起時,才會產生真正的 Privilege。這就是 Privilege Instance。許可權系統根據需求的不同可以延伸生很多不同的版本。
Role:是粗粒度和細粒度(業務邏輯)的介面,一個基於粗粒度控制的許可權框架軟體,對外的介面應該是Role,具體業務實現可以直接繼承或擴充豐富Role的內容,Role不是如同User或Group的具體實體,它是介面概念,抽象的通稱。
Group:使用者組,許可權分配的單位與載體。許可權不考慮分配給特定的使用者。組可以包括組(以實現許可權的繼承)。組可以包含使用者,組內使用者繼承組的許可權。Group要實現繼承。即在建立時必須要指定該Group的Parent是什麼Group。在粗粒度控制上,可以認為,只要某使用者直接或者間接的屬於某個Group那麼它就具備這個Group的所有操作許可。細粒度控制上,在業務邏輯的判斷中,User僅應關注其直接屬於的Group,用來判斷是否“同組” 。Group是可繼承的,對於一個分級的許可權實現,某個Group透過“繼承”就已經直接獲得了其父Group所擁有的所有“許可權集合”,對這個Group而言,需要與許可權建立直接關聯的,僅是它比起其父Group需要“擴充套件”的那部分許可權。子組繼承父組的所有許可權,規則來得更簡單,同時意味著管理更容易。為了更進一步實現許可權的繼承,最直接的就是在Group上引入“父子關係”。
User與Group是多對多的關係。即一個User可以屬於多個Group之中,一個Group可以包括多個User。子Group與父Group是多對一的關係。Operator某種意義上類似於Resource + Privilege概念,但這裡的Resource僅包括Resource Type不表示Resource Instance。Group 可以直接對映組織結構,Role 可以直接對映組織結構中的業務角色,比較直觀,而且也足夠靈活。Role對系統的貢獻實質上就是提供了一個比較粗顆粒的分配單位。
Group與Operator是多對多的關係。各概念的關係圖示如下:
解釋:
Operator的定義包括了Resource Type和Method概念。即,What和How的概念。之所以將What和How繫結在一起作為一個Operator概念而不是分開建模再建立關聯,這是因為很多的How對於某What才有意義。比如,釋出操作對新聞物件才有意義,對使用者物件則沒有意義。
How本身的意義也有所不同,具體來說,對於每一個What可以定義N種操作。比如,對於合同這類物件,可以定義建立操作、提交操作、檢查衝突操作等。可以認為,How概念對應於每一個商業方法。其中,與具體使用者身份相關的操作既可以定義在操作的業務邏輯之中,也可以定義在操作級別。比如,建立者的瀏覽檢視與普通使用者的瀏覽檢視要求內容不同。既可以在外部定義兩個操作方法,也可以在一個操作方法的內部根據具體邏輯進行處理。具體應用哪一種方式應依據實際情況進行處理。
這樣的架構,應能在易於理解和管理的情況下,滿足絕大部分粗粒度許可權控制的功能需要。但是除了粗粒度許可權,系統中必然還會包括無數對具體Instance的細粒度許可權。這些問題,被留給業務邏輯來解決,這樣的考慮基於以下兩點:
一方面,細粒度的許可權判斷必須要在資源上建模許可權分配的支援資訊才可能得以實現。比如,如果要求建立者和普通使用者看到不同的資訊內容,那麼,資源本身應該有其建立者的資訊。另一方面,細粒度的許可權常常具有相當大的業務邏輯相關性。對不同的業務邏輯,常常意味著完全不同的許可權判定原則和策略。相比之下,粗粒度的許可權更具通用性,將其實現為一個架構,更有重用價值;而將細粒度的許可權判斷實現為一個架構級別的東西就顯得繁瑣,而且不是那麼的有必要,用定製的程式碼來實現就更簡潔,更靈活。
所以細粒度控制應該在底層解決,Resource在例項化的時候,必需指定Owner和GroupPrivilege在對Resource進行操作時也必然會確定約束型別:究竟是OwnerOK還是GroupOK還是AllOK。Group應和Role嚴格分離User和Group是多對多的關係,Group只用於對使用者分類,不包含任何Role的意義;Role只授予User,而不是Group。如果使用者需要還沒有的多種Privilege的組合,必須新增Role。Privilege必須能夠訪問Resource,同時帶User引數,這樣許可權控制就完備了。
思想:
許可權系統的核心由以下三部分構成:1.創造許可權,2.分配許可權,3.使用許可權,然後,系統各部分的主要參與者對照如下:1.創造許可權 - Creator創造,2.分配許可權 - Administrator 分配,3.使用許可權 - User:
1. Creator 創造 Privilege, Creator 在設計和實現系統時會劃分,一個子系統或稱為模組,應該有哪些許可權。這裡完成的是 Privilege 與 Resource 的物件宣告,並沒有真正將 Privilege 與具體Resource 例項聯絡在一起,形成Operator。
2. Administrator 指定 Privilege 與 Resource Instance 的關聯。在這一步, 許可權真正與資源例項聯絡到了一起, 產生了Operator(Privilege Instance)。Administrator利用Operator這個基本元素,來創造他理想中的許可權模型。如,建立角色,建立使用者組,給使用者組分配使用者,將使用者組與角色關聯等等...這些操作都是由 Administrator 來完成的。
3. User 使用 Administrator 分配給的許可權去使用各個子系統。Administrator 是使用者,在他的心目中有一個比較適合他管理和維護的許可權模型。於是,程式設計師只要回答一個問題,就是什麼許可權可以訪問什麼資源,也就是前面說的 Operator。程式設計師提供 Operator 就意味著給系統穿上了盔甲。Administrator 就可以按照他的意願來建立他所希望的許可權框架可以自行增加,刪除,管理Resource和Privilege之間關係。可以自行設定使用者User和角色Role的對應關係。(如果將 Creator看作是 Basic 的發明者, Administrator 就是 Basic 的使用者,他可以做一些指令碼式的程式設計) Operator是這個系統中最關鍵的部分,它是一個紐帶,一個系在Programmer,Administrator,User之間的紐帶。
用一個功能模組來舉例子。
一.建立角色功能並做分配:
1.如果現在要做一個員工管理的模組(即Resources),這個模組有三個功能,分別是:增加,修改,刪除。給這三個功能各自分配一個ID,這個ID叫做功能代號:
Emp_addEmp,Emp_deleteEmp,Emp_updateEmp。
2.建立一個角色(Role),把上面的功能程式碼加到這個角色擁有的許可權中,並儲存到資料庫中。角色包括系統管理員,測試人員等。
3.建立一個員工的賬號,並把一種或幾種角色賦給這個員工。比如說這個員工既可以是公司管理人員,也可以是測試人員等。這樣他登入到系統中將會只看到他擁有許可權的那些模組。
二.把身份資訊加到Session中。
登入時,先到資料庫中查詢是否存在這個員工,如果存在,再根據員工的sn查詢員工的許可權資訊,把員工所有的許可權資訊都入到一個Hashmap中,比如就把上面的Emp_addEmp等放到這個Hashmap中。然後把Hashmap儲存在一個UserInfoBean中。最後把這個UserInfoBean放到Session中,這樣在整個程式的執行過程中,系統隨時都可以取得這個使用者的身份資訊。
三.根據使用者的許可權做出不同的顯示。
可以對比當前員工的許可權和給這個選單分配的“功能ID”判斷當前使用者是否有開啟這個選單的許可權。例如:如果儲存員工許可權的Hashmap中沒有這三個ID的任何一個,那這個選單就不會顯示,如果員工的Hashmap中有任何一個ID,那這個選單都會顯示。
對於一個新聞系統(Resouce),假設它有這樣的功能(Privilege):檢視,釋出,刪除,修改;假設對於刪除,有"新聞系統管理者只能刪除一月前釋出的,而超級管理員可刪除所有的這樣的限制,這屬於業務邏輯(Business logic),而不屬於使用者許可權範圍。也就是說許可權負責有沒有刪除的Permission,至於能刪除哪些內容應該根據UserRole or UserGroup來決定(當然給UserRole or UserGroup分配許可權時就應該包含上面兩條業務邏輯)。
一個使用者可以擁有多種角色,但同一時刻使用者只能用一種角色進入系統。角色的劃分方法可以根據實際情況劃分,按部門或機構進行劃分的,至於角色擁有多少許可權,這就看系統管理員賦給他多少的許可權了。使用者―角色―許可權的關鍵是角色。使用者登入時是以使用者和角色兩種屬性進行登入的(因為一個使用者可以擁有多種角色,但同一時刻只能扮演一種角色),根據角色得到使用者的許可權,登入後進行初始化。這其中的技巧是同一時刻某一使用者只能用一種角色進行登入。
針對不同的“角色”動態的建立不同的組,每個專案建立一個單獨的Group,對於新的專案,建立新的 Group 即可。在許可權判斷部分,應在商業方法上予以控制。比如:不同使用者的“操作能力”是不同的(粗粒度的控制應能滿足要求),不同使用者的“可視區域”是不同的(體現在對被操作的物件的許可權資料,是否允許當前使用者訪問,這需要對業務資料建模的時候考慮許可權控制需要)。
擴充套件性:
有了使用者/許可權管理的基本框架,Who(User/Group)的概念是不會經常需要擴充套件的。變化的可能是系統中引入新的 What (新的Resource型別)或者新的How(新的操作方式)。那在三個基本概念中,僅在Permission上進行擴充套件是不夠的。這樣的設計中Permission實質上解決了How 的問題,即表示了“怎樣”的操作。那麼這個“怎樣”是在哪一個層次上的定義呢?將Permission定義在“商業方法”級別比較合適。比如,釋出、購買、取消。每一個商業方法可以意味著使用者進行的一個“動作”。定義在商業邏輯的層次上,一方面保證了資料訪問程式碼的“純潔性”,另一方面在功能上也是“足夠”的。也就是說,對更低層次,能自由的訪問資料,對更高層次,也能比較精細的控制許可權。
確定了Permission定義的合適層次,更進一步,能夠發現Permission實際上還隱含了What的概念。也就是說,對於What的How操作才會是一個完整的Operator。比如,“釋出”操作,隱含了“資訊”的“釋出”概念,而對於“商品”而言釋出操作是沒有意義的。同樣的,“購買”操作,隱含了“商品”的“購買”概念。這裡的繫結還體現在大量通用的同名的操作上,比如,需要區分“商品的刪除”與“資訊的刪除”這兩個同名為“刪除”的不同操作。
提供許可權系統的擴充套件能力是在Operator (Resource + Permission)的概念上進行擴充套件。Proxy 模式是一個非常合適的實現方式。實現大致如下:在業務邏輯層(EJB Session Facade [Stateful SessionBean]中),取得該商業方法的Methodname,再根據Classname和 Methodname 檢索Operator 資料,然後依據這個Operator資訊和Stateful中儲存的User資訊判斷當前使用者是否具備該方法的操作許可權。
應用在 EJB 模式下,可以定義一個很明確的 Business層次,而一個Business 可能意味著不同的檢視,當多個檢視都對應於一個業務邏輯的時候,比如,Swing Client以及 Jsp Client 訪問的是同一個 EJB 實現的 Business。在 Business 層上應用許可權較能提供集中的控制能力。實際上,如果許可權系統提供了查詢能力,那麼會發現,在檢視層次已經可以不去理解許可權,它只需要根據查詢結果控制介面就可以了。
靈活性:
Group和Role,只是一種輔助實現的手段,不是必需的。如果系統的Role很多,逐個授權違背了“簡單,方便”的目的,那就引入Group,將許可權相同的Role組成一個Group進行集中授權。Role也一樣,是某一類Operator的集合,是為了簡化針對多個Operator的操作。
Role把具體的使用者和組從許可權中解放出來。一個使用者可以承擔不同的角色,從而實現授權的靈活性。當然,Group也可以實現類似的功能。但實際業務中,Group劃分多以行政組織結構或業務功能劃分;如果為了許可權管理強行將一個使用者加入不同的組,會導致管理的複雜性。
Domain的應用。為了授權更靈活,可以將Where或者Scope抽象出來,稱之為Domain,真正的授權是在Domain的範圍內進行,具體的Resource將分屬於不同的Domain。比如:一個新聞機構有國內與國外兩大分支,兩大分支內又都有不同的資源(體育類、生活類、時事政治類)。假如所有國內新聞的許可權規則都是一樣的,所有國外新聞的許可權規則也相同。則可以建立兩個域,分別授權,然後只要將各類新聞與不同的域關聯,受域上的許可權控制,從而使之簡化。
許可權系統還應該考慮將功能性的授權與資源性的授權分開。很多系統都只有對系統中的資料(資源)的維護有許可權控制,但沒有對系統功能的許可權控制。
許可權系統最好是可以分層管理而不是集中管理。大多客戶希望不同的部門能且僅能管理其部門內部的事務,而不是什麼都需要一個集中的Administrator或Administrators組來管理。雖然你可以將不同部門的人都加入Administrators組,但他們的許可權過大,可以管理整個系統資源而不是該部門資源。
正向授權與負向授權:正向授權在開始時假定主體沒有任何許可權,然後根據需要授予許可權,適合於許可權要求嚴格的系統。負向授權在開始時假定主體有所有許可權,然後將某些特殊許可權收回。
許可權計算策略:系統中User,Group,Role都可以授權,許可權可以有正負向之分,在計算使用者的淨許可權時定義一套策略。
系統中應該有一個集中管理許可權的AccessService,負責許可權的維護(業務管理員、安全管理模組)與使用(終端使用者、各功能模組),該AccessService在實現時要同時考慮一般許可權與特殊許可權。雖然在具體實現上可以有很多,比如用Proxy模式,但應該使這些Proxy依賴於AccessService。各模組功能中呼叫AccessService來檢查是否有相應的許可權。所以說,許可權管理不是安全管理模組自己一個人的事情,而是與系統各功能模組都有關係。每個功能模組的開發人員都應該熟悉安全管理模組,當然,也要從業務上熟悉本模組的安全規則。
技術實現:
1.表單式認證,這是常用的,但使用者到達一個不被授權訪問的資源時,Web容器就發
出一個html頁面,要求輸入使用者名稱和密碼。
2.一個基於Servlet Sign in/Sign out來集中處理所有的Request,缺點是必須由應用程式自己來處理。
3.用Filter防止使用者訪問一些未被授權的資源,Filter會擷取所有Request/Response,
然後放置一個驗證透過的標識在使用者的Session中,然後Filter每次依靠這個標識來決定是否放行Response。
這個模式分為:
Gatekeeper :採取Filter或統一Servlet的方式。
Authenticator: 在Web中使用JAAS自己來實現。
使用者資格儲存LDAP或資料庫:
1. Gatekeeper攔截檢查每個到達受保護的資源。首先檢查這個使用者是否有已經建立
好的Login Session,如果沒有,Gatekeeper 檢查是否有一個全域性的和Authenticator相關的session?
2. 如果沒有全域性的session,這個使用者被導向到Authenticator的Sign-on 頁面,
要求提供使用者名稱和密碼。
3. Authenticator接受使用者名稱和密碼,透過使用者的資格系統驗證使用者。
4. 如果驗證成功,Authenticator將建立一個全域性Login session,並且導向Gatekeeper
來為這個使用者在他的web應用中建立一個Login Session。
5. Authenticator和Gatekeepers聯合分享Cookie,或者使用Tokens在Query字元裡。

相關文章