續:關於許可權系統的設計

jackyz發表於2002-12-07
Note:
首先,向版主致歉。這原是關於許可權系統設計問題的回帖,本不應該另開新貼。而在下的另開新貼,一方面是因為本人的觀點中與很多人的觀點差別較大,另一方面也擔心其會被“埋沒”在原貼的大量回帖中。此外,本貼的內容整理與編排耗費了我週末接近一整個晚上的時間,包含了我對近期專案中許可權系統的思考與總結,希望引來大家足夠的目光和指導。請版主體諒。


許可權系統,其重要性當然不言自明。看見大家的方案,有相當多優秀的創意與經驗,我的專案也有所涉及,以下說明的是我最近在一個企業 EJB 專案中初步實現的方案(以及設計考量),望與諸位共商榷。


前言:

許可權往往是一個極其複雜的問題,但也可簡單表述為這樣的邏輯表示式:判斷“who 對 what(which) 進行 how 的操作”的邏輯表示式是否為真。

針對不同的應用,需要根據專案的實際情況和具體架構,在維護性、靈活性、完整性等N多個方案之間比較權衡,選擇符合的方案。


目標:

這個許可權系統的設計,我主要考慮了這麼幾個目標:

直觀,因為系統最終會由終端使用者來維護,許可權分配的直觀和容易理解,顯得比較重要,系統不辭勞苦的實現了組的繼承,除了功能的必須,更主要的就是因為它足夠直觀。

簡單,包括概念數量上的簡單和意義上的簡單還有功能上的簡單。想用一個許可權系統解決所有的許可權問題是不現實的。設計中將常常變化的“定製”特點比較強的部分判斷為業務邏輯,而將常常相同的“通用”特點比較強的部分判斷為許可權邏輯就是基於這樣的思路。此外,同時具備 Role 和 Group 的系統難於理解,權衡之下,摒棄了 Role 概念。

擴充套件,我在以前的專案中也實現過基於 Role 概念的許可權系統,但效果不太理想。之所以在這裡摒棄 Role 的概念,另一個原因就是因為它不易擴充套件。通常 Role 的設計方式意味著預先已經定好了一組許可權,這樣的“預先設計”,常常會鼓勵程式設計師 hardcode 這些許可權相關的部分,而,如果這麼做的話,當需要重新定義 Role 時,擴充套件就會變得極為困難。而採用可繼承的 Group 概念在支援許可權以組方式定義的同時有效避免了重定義時在擴充套件上的困難。


名詞:

下面兩個名詞極其重要,是整個設計問題邊界定義的關鍵,或許我的理解與通常的理解不同,在此有必要特別澄清。

粗粒度:表示類別級,即,僅考慮物件的類別,不考慮物件的某個特定例項。比方,使用者管理中,建立、刪除,對所有的使用者都一視同仁,並不區分操作的具體物件例項。

細粒度:表示例項級,即,需要考慮具體物件的例項,當然,細粒度是在考慮粗粒度的物件類別之後才再考慮特定例項。比方,合同管理中,列表、刪除,需要區分該合同例項是否為當前使用者所建立。


原則:

許可權邏輯配合業務邏輯。即,許可權系統以為業務邏輯提供服務為目標。純粹紙面意義的極其複雜和精巧的許可權系統,這裡不作討論。相當多細粒度的許可權問題因其極其獨特而不具通用意義,它們也能被理解為是“業務邏輯”的一部分。比方,要求:“合同資源只能被它的建立者刪除,與建立者同組的使用者可以修改,所有的使用者能夠瀏覽”。這既可以認為是一個細粒度的許可權問題,也可以認為是一個業務邏輯問題。在這裡我認為它是業務邏輯問題,在整個許可權系統的架構設計之中不予過多考慮。當然,許可權系統的架構也必須要能支援這樣的控制判斷。或者說,系統提供足夠多但不是完全的控制能力。即,設計原則歸結為:“系統只提供粗粒度的許可權,細粒度的許可權被認為是業務邏輯的職責”。

需要再次強調的是,這裡表述的許可權系統僅是一個“不完全”的許可權系統,即,它不提供所有關於許可權的問題的解決方法。它提供一個基礎,並解決那些具有“共性”的(或者說粗粒度的)部分。在這個基礎之上,根據“業務邏輯”的獨特許可權需求,編碼實現剩餘部分(或者說細粒度的)部分,才算完整。回到許可權的問題公式,我的設計僅解決了 who + what + how 的問題,which 的許可權問題留給業務邏輯解決。


概念:

User:使用者。解決 who 的問題。

Group:組。許可權分配的單位與載體。許可權不考慮分配給特定的使用者。組可以包括組(以實現許可權的繼承)。

Operate:操作。表明對 what 的 how 操作。


說明:

User

與大家的都一樣,沒什麼好說的。

Group

與大家的類似,所不同的是,Group 要實現繼承。即,在建立時必須要指定該 Group 的 Parent 是什麼 Group 。在粗粒度控制上,可以認為,只要某使用者直接或者間接的屬於某個 Group 那麼它就具備這個 Group 的所有操作許可。細粒度控制上,在業務邏輯的判斷中,User 僅應關注其直接屬於的 Group ,用來判斷是否“同組”,間接的 Group 對許可權的控制意義不大,試設想存在一個 All User 的 Group 是所有 Group 的祖先,這樣的情形下,判斷的結果不具備實際意義。

User 與 Group 是多對多的關係。即,一個 User 可以屬於多個 Group 之中,一個 Group 可以包括多個 User 。

子 Group 與 父 Group 是多對一的關係。即,一個子 Group 只能有一個父 Group ,一個父 Group 可以包括多個子 Group 。


Operate

某種意義上類似於大家的 Resource + Privilege 概念,但,這裡的 Resource 僅包括 Resource Type 不表示 Resource Instance。Operate 概念上與大家的觀點區別比較,後面有詳細的解釋。

Group 與 Operate 是多對多的關係。

各概念的關係圖示如下:

 User
  |*
  |
  |*   1
 Group---+
  |* |*  |
  |  +---+
  |*
 Operate
<p class="indent">


解釋:

Operate 的定義包括了 Resource Type 和 Method 概念。即, what 和 how 的概念。之所以將 what 和 how 繫結在一起作為一個 Operate 概念而不是分開建模再建立關聯,這是因為很多的 how 對於某 what 才有意義。比方,釋出操作對新聞物件才有意義,對使用者物件則沒有意義。

how 本身的意義也有所不同,這裡並非僅定義類 UNIX 的 RWX 三種操作,這樣的定義對於檔案系統是合理的,但,對於其他的應用領域或許就不是那麼足夠了。具體來說,對於每一個 what 可以定義 N 種操作。比方,對於合同這類物件,可以定義建立操作、提交操作、檢查衝突操作等。可以認為,how 概念對應於每一個商業方法。

其中,與具體使用者身份相關的操作既可以定義在操作的業務邏輯之中,也可以定義在操作級別。比方,建立者的瀏覽檢視與普通使用者的瀏覽檢視要求內容不同。你既可以在外部定義兩個操作方法,也可以在一個操作方法的內部根據具體邏輯進行處理。具體應用哪一種方式應依據實際情況進行處理。

這樣的架構,應能在易於理解和管理的情況下,滿足絕大部分粗粒度許可權控制的功能需要。但是,除了粗粒度許可權,無可否認,系統中必然還會包括無數對具體 Instance 的細粒度許可權。這些問題,被留給業務邏輯來解決,這樣的考慮基於以下兩點。

一方面,細粒度的許可權判斷必須要在資源上建模許可權分配的支援資訊才可能得以實現。比方,如果要求建立者和普通使用者看到不同的資訊內容,那麼,資源本身應該有其建立者的資訊。如同 Unix 的每一個檔案(資源),都定義了對 Owner, Group, All 的不同操作屬性。

另一方面,細粒度的許可權常常具有相當大的業務邏輯相關性。對不同的業務邏輯,常常意味著完全不同的許可權判定原則和策略。相比之下,粗粒度的許可權更具通用性,將其實現為一個架構,更有重用價值;而將細粒度的許可權判斷實現為一個架構級別的東西就顯得繁瑣,而且不是那麼的有必要,用定製的程式碼來實現就更簡潔,更靈活。


結語:

希望我的文字表述清楚,也希望我的方案能激起大家討論研究的興趣。

歡迎討論。

相關文章