權限系統(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的模式切換)。更復雜一些,
在不同的時刻, 我們需要根據其他附加信息來作出是否允許操作的判斷, 即此時我們權限設置的不僅僅是一些靜態的描述信息, 而是一個完整的控制函數,
這就是所謂的工作流權限控制,一種動態權限控制.
權限系統(2)--operation
權限控制可以看作一個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方式實現細粒度訪問控制,困難似乎在于不容易引入外部配置信息(例如功能點信息等),而且控制點所對應的對象函數格式也不統一,因而多數需要在細粒度上一一指定。
權限系統(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./oracle/or-articles/tropashko4
權限系統(5)--動態性
動態權限最簡單的一個表現是時限性,subject只在某個時間段內具有某種權限。這只需要在user和role的映射中,或者role自身的屬性中增加startTime和expireTime即可。
更復雜的動態性一般與流程控制相關,此時權限控制應該由工作流系統完成,而不是在數據上增加越來越多的權限標記。在witrix平臺中,使用tpl模板技術來定制權限設置。
|