前言:
權限每每是一個極其複雜的問題,但也可簡單表述爲這樣的邏輯表達式:判斷"Who對What(Which)進行How的操做"的邏輯表達式是否爲真。針對 不一樣的應用,須要根據項目的實際狀況和具體架構,在維護性、靈活性、完整性等N多個方案之間比較權衡,選擇符合的方案。ghtml
目標:
直觀,由於系統最終會由最終用戶來維護,權限分配的直觀和容易理解,顯得比較重要,系統不辭勞苦的實現了組的繼承,除了功能的必須,更主要的就是由於它足夠直觀。
簡單,包括概念數量上的簡單和意義上的簡單還有功能上的簡單。想用一個權限系統解決全部的權限問題是不現實的。設計中將經常變化的"定製"特色比較強的部分判斷爲業務邏輯,而將經常相同的"通用"特色比較強的部分判斷爲權限邏輯就是基於這樣的思路。
擴展,採用可繼承在擴展上的困難。的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字符裏。
---------------------------------------------------------------
程序員
權限系統(1)--基本模式
在系統中發生的事情,抽象的說都是某個主體(subject)在某個資源(resource)上執行了某個操做(operation)。
subject --[operation]--> resource
所謂權限管理,就是在這條信息傳遞路徑中加上一些限制性控制。
主體試圖去作的 limited by 系統容許主體去作的 = 主體實際作的。
能夠看到,權限控制基本對應於filter模式。subject試圖去作的事情應該由業務邏輯決定,於是應該編碼在業務系統中。
先考慮最粗粒度的控制策略,控制點加在subject處,即不管從事何種操做,針對何種資源,咱們首先須要確認subject是受控的。只有經過認證的用戶才能使用系統功能,這就是authentication。boolean isAllowed subject)
稍微複雜一些,控制能夠施加在subject和operation的邊界處(此時並不知道具體進行何種操做),稱爲模塊訪問控制,即只有某些用戶才能訪問特定模塊。isAllowed(subject, operation set)
第三級控制直接施加在operation上,即操做訪問控制。operation知道resource和subject(但它尚沒有關於resource的細節知識),咱們可以採起的權限機制是bool isAllowed(subject, operation, resource), 返回true容許操做,返回false則不容許操做。
最簡單的狀況下,subject與resource之間的訪問控制關係是靜態的,能夠直接寫成一個權限控制矩陣
for operationA:
resourceA resourceB
subjectA 1 0
subjectB 0 1
isAllowed(subjectA, resourceA)恆等於true
若是多個operation的權限控制均可以經過這種方式來表示,則多個權限控制矩陣能夠疊加在一塊兒
for operationA, operationB:
resourceA resourceB
subjectA 10 01
subjectB 01 11
當subject和resource的種類不少時,權限控制矩陣急劇膨脹,它的條目數是N*M。很顯然,咱們須要進行矩陣分解。這也是最基本的控制手段之一: 在系統中增長一個瓶頸,或者說尋找到隱含的結構。
subject_resource = subject_role * role_resource
這樣系統權限配置條目的數量爲 N*R + R*M, 若是R的數目遠小於subject和resource,則實現簡化。這稱爲RBAC(role based access control),它的一個額外好處是權限系統的部分描述能夠獨立於subject存在,即在系統中沒有任何用戶的時候,經過角色仍然能夠表達部分權限信息。能夠說角色是subject在權限系統中的代理(分解)。
有時候引入一個瓶頸還不過癮,有人引入組的概念,與role串聯,
subject_resource = subject_group_role * role_resource
或着group與role並聯,
subject_resource = subject_group * group_resource
與role稍有不一樣,通常狀況下group的業務含義更加明顯,可能對應於組織結構等。將組織機構明確引入權限體系,有的時候比較方便,但對於權限系統自 身的穩定性而言,未見得有什麼太大的好處。並聯模式有些多餘,串聯模式又過於複雜,細節調整困難,特別是多條控制路徑形成的衝突狀況。通常狀況下,我不提 倡將group引入權限控制中。
比操做控制更加深刻的控制就是數據控制了,此時須要對於resource的比較全面的知識。雖然表面上,仍然是
boolean isAllowed(subject, operation, resource),但控制函數須要知道resource的細節。例如行級控制(row-level)或者列級控制(column-level)的實現。 由於咱們通常狀況下不可能將每個條目都建模爲獨立的resource,而只能是存在一個總體描述,例如全部密級爲絕密的文檔。在witrix平臺中,數 據控制主要經過數據源的filter來實現,由於查詢條件(數據的定位條件)已經被對象化爲Query類,因此咱們能夠在合適的地方自由的追加權限控制條 件。
以上的討論中,權限控制都是根據某些靜態描述信息來進行的,但現實世界是多變的。最簡單的,當subject從事不一樣業務時,對應於同一組資源,也可能對應的權限控制並不一樣(在witrix平臺中,對應於IDataSource的模式切換)。更復雜一些, 在不一樣的時刻, 咱們須要根據其餘附加信息來做出是否容許操做的判斷, 即此時咱們權限設置的不只僅是一些靜態的描述信息, 而是一個完整的控制函數, 這就是所謂的工做流權限控制,一種動態權限控制.web
權限系統(2)--operationspring
權限控制能夠看做一個filter模式的應用, 這也符合AOP思想的應用條件。在一個簡化的圖象中,咱們只須要將一個判別函數 isAllowed(subject, operation, resource)插入到全部安全敏感的函數調用以前就能夠了。雖然概念上很完美,具體實現的時候仍然有一些細節上的問題。基本的困難在於很難在最細的粒 度上指定權限控制規則(連續的?動態的?可擴展的?),於是咱們只能在一些關鍵處指定權限規則,或者設置一些總體性的權限策略,而後經過特定的推理來推導 出細粒度的權限規則,這就引出結構的問題。咱們須要可以對權限控制策略進行有效的描述(控制策略的結構),而且決定如何與程序結構相結合。 subject, operation和resource爲了支持推理,均可能須要分化出複雜的結構,而再也不是簡單的原子性的概念。而在與程序結構結合這一方面,雖然AOP 使得咱們能夠擴展任何函數,但這種擴展須要依賴於cutpoint處所能獲得的信息,於是權限控制的有效實施也很是依賴於功能函數自己良好的設計。有的時 候由於須要對結構有過於明確的假定,權限控制的實現不得不犧牲必定的通用性。
下面咱們將分別討論一下operation, subject和resource的結構分解的問題。首先是operation。
說到推理結構,讓人最早想起的就是決策樹,樹形結構,在面嚮對象語言中能夠對應於繼承。金字塔式的樹形結構也正是在現實世界中咱們應用最多的控制結構。經過層層分解,operation的結構能夠組織爲一棵樹,
應用程序 ==> 各個子系統 ==> 每一個子系統的功能模塊 ==> 子功能模塊
==> 每一個模塊的功能點(具備明確的業務含義) ==> 每一個功能點對應的訪問函數(程序實現中的結構)
一個常見的需求是根據權限配置決定系統菜單樹的顯示,通常控制用戶只能看到本身有權操做的功能模塊和功能按鈕。這種需求的解決方法是很是直接的。首先,在 後臺創建子系統到功能模塊,功能模塊到功能點以及功能點到實現函數之間的映射表(若是程序組織具備嚴格規範,這甚至能夠經過自動蒐集獲得)。而後,在權限 配置時創建用戶與功能點之間的關聯。此時,經過一個視圖,咱們就能夠蒐集到用戶對哪些功能模塊具備訪問權限的信息。
爲了控制菜單樹的顯示,witrix平臺中的SiteMap採用以下策略:
1. 若是用戶對某個子功能具備操做權限,則全部父菜單項都缺省可用
2. 若是用戶對某個功能具備操做權限,而且標記爲cascade,則全部子菜單項都自動缺省可用
3. 若是明確指定功能不可用,則該菜單及子菜單都強制不可用
4. 若是明確指定功能對全部人可用,則不驗證權限,全部子菜單自動缺省可用
4. 強制設定覆蓋缺省值
5. 不可用的菜單缺省不可見
6. 明確標記爲可見的菜單即便不可用也可見
7. 父菜單可見子菜單纔可見
咱們經過預計算來綜合考慮這些相互影響的控制策略。儘可能將推導運算預先完成也是解決性能問題的不二法門。
在witrix平臺中,每一次網絡訪問的url都符合jsplet框架所要求的對象調用格式,須要指定objectName和objectEvent參 數,這就對應於功能點的訪問函數。訪問控制點集中在objectManager而且訪問格式是標準的。使用spring等AOP方式實現細粒度訪問控制, 困難彷佛在於不容易引入外部配置信息(例如功能點信息等),並且控制點所對應的對象函數格式也不統一,於是多數須要在細粒度上一一指定。sql
權限系統(3)-- subject數據庫
權限控制中,subject可能不會簡單的對應於userId, 而是包含一系列的security token或certificate, 例如用戶登錄地址,登錄時間等。通常狀況下,這些信息在權限系統中的使用都是很直接的,不會形成什麼問題。
subject域中最重要的結構是user和role的分離,能夠在不存在user的狀況下,爲role指定權限。有人進一步定義了userGroup的 概念,能夠爲userGroup指定role,而user從其所屬的group繼承role的設置。通常狀況下,我不提倡在權限系統中引入 userGroup的概念。這其中最重要的緣由就是它會形成多條權限信息傳遞途徑,從而產生一種路徑依賴, 並可能出現信息衝突的狀況。通常user與group的關聯具備明確的業務含義,於是不能隨意取消。若是咱們但願對user擁有的權限進行細調,除去 user從group繼承的某個不該該擁有的權限,解決的方法頗有多是所謂的負權限,即某個權限條目描述的是不能作某某事。負權限會形成各個權限設置之 間的互相影響,形成必須嘗試全部權限規則才能做出判斷的困境,引出對額外的消歧策略的需求,這些都極大的限制了系統的可擴展性。在容許負權限的環境中,管 理員將沒法直接判定某個權限設置的最終影響,他必須在頭腦中完成全部的權限運算以後才能理解某用戶最終擁有的實際權限,若是發現權限設置衝突,管理員可能 須要屢次嘗試才能找到合適方案。這種配置時的推理需求可能會增長配置管理的難度,形成微妙的安全漏洞,並且負權限致使的全局關聯也下降了權限系統的穩定 性。我更傾向於將group做爲權限設置時的一種輔助標記手段,系統中只記錄用戶最終擁有的角色,即至關於記錄用戶經過group擁有權限的推導完成的結 果, 若是須要權限細調,咱們直接在用戶擁有的角色列表上直接進行。固然,若是實現的複雜一些,權限系統對外暴露的接口仍然能夠模擬爲可以指定 userGroup的權限。
推理在面嚮對象語言中最明顯的表現是繼承,因此有些人將subject域中的推理直接等價於role之間的繼承問題,這未必是最好的選擇。繼承能夠造成非 常複雜的推理關係,可是可能過於複雜了(特別是直接使用sql語句沒法實現樹形推理查詢)。按照級列理論,從不相關發展到下一階段是出現簡單的序關係,即 咱們能夠說subject出現級別上的差別,高級別subject將自動具備低級別的權限。一種選擇是定義roleRank,規定高級別role自動具備 低級別role的權限,但考慮到user與role的兩分結構,咱們也能夠同時定義userRank和roleRank,規定高級別user自動具備低級 別的role,而role之間不具備推理關係。在面向對象領域中,咱們已經證明了徹底採用繼承來組織對象關係會致使系統的不穩定,因此我傾向於第二種選 擇,即將role看做某種相似於interface的東西,一種權限的切片。爲了進一步限制這種推導關係,咱們能夠定義所謂的安全域的概念. security domain, 規定推導只能在必定的域中才能進行。
select user.userId, role.roleId
from user, role
where user.userRank > role.roleRank
and user.domain = role.domain
將權限控制通常須要施加在最細的粒度上,這在複雜的系統中可能過於理想化了。複雜的狀況下咱們須要進行局部化設計,即進行某些敏感操做以前進行一系列複雜的權限校驗工做。當完成這些工做以後,進入某個security zone, 在其中進行操做就再也不須要校驗了。
總的來講,權限系統採用很是複雜的結構效果未必理想。不少時候只是個管理模式的問題,應該儘可能經過從新設計權限空間的結構來加以規避。不過在一些很是複雜 的權限控制環境下,也許簡單的描述信息確實很難有效的表達權限策略(雖然我從未遇到過),此時嘗試一下規則引擎可能比在權限系統中強行塞入愈來愈多的約束 要好的多
權限系統(4)--resource編程
權限管理中進行數據訪問控制,其基本模式以下
operation target = selector(resource)
selector = user selector + auth filter
這裏須要對resource的結構,以及選擇算子的顯式建模。selector必須容許權限系統追加filter,例如
IDataSource包中所使用的Query對象。
sql語言的表達能力有限, 做爲選擇算子來使用有時須要resource做一些結構上的調整,增長一些冗餘的字段。例如表達一段時間內的利率,咱們須要使用from_date和to_date兩個字段來進行描述,其中to_date的值與下一條記錄的from_date相同。
value from_date to_date
0.01 2003-01-01 2003-05-01
0.012 2003-05-01 2004-01-01
若是表達一條航線中的多個階段,咱們可能會在每條記錄中增長起始站和終點站兩個字段。
更重要的一個常見需求是樹形結構在關係數據庫中的表達。爲了可以直接操縱一個分支下的全部記錄,在層次固定的狀況下,咱們可能會增長多個分類字段,例如數 據倉庫中的層次維度。在層次數目不肯定的狀況下,咱們將不得不使用層次碼或者相似於url的其餘方案,經過layer_code like '01.01.%' 之類的語句實現分支選擇。爲了限制選擇的深度,咱們可能還須要layer_level字段。基於層次碼和層次數,咱們能夠創建多種選擇算子,例如包含全部 直接子節點,包含自身及全部父節點等等。
http://www.dbazine.com/oracle/or-articles/tropashko4瀏覽器
權限系統(5)--動態性安全
動態權限最簡單的一個表現是時限性,subject只在某個時間段內具備某種權限。這隻須要在user和role的映射中,或者role自身的屬性中增長startTime和expireTime便可。
更復雜的動態性通常與流程控制相關,此時權限控制應該由工做流系統完成,而不是在數據上增長愈來愈多的權限標記。在witrix平臺中,使用tpl模板技術來定製權限設置。
http://canonical.blogdriver.com/canonical/658364.html服務器