權(quán)限模塊是業(yè)務系統(tǒng)最常見、最基本的子集。本章假定了一個系統(tǒng)從最初簡單的需求到逐漸成熟且完善的權(quán)限體系的實現(xiàn)過程。 閱讀本章預計花費20分鐘。 1. 最簡單的權(quán)限模型業(yè)務系統(tǒng)初期,需求簡單,對于權(quán)限的內(nèi)容本身并不復雜,我們假設權(quán)限部分僅有這樣簡單的需求:
分析此需求,權(quán)限的主體為用戶,權(quán)限的內(nèi)容有多種,關系為M - M,具體為:
用戶表Auth_User
權(quán)限枚舉:
權(quán)限表 Auth_Permission
用戶-權(quán)限關系表 Auth_UserPermission
假如一個用戶有增、改兩種權(quán)限,那么關系表(Auth_UserPermission)可以存儲為:
于是對于權(quán)限的基本操作我們可以進行歸納:
我們留意到對于Permission的枚舉定義,值使用了對2的冪運算的值:
這么定義是有好處的,對于Auth_UserPermission的表存儲可以節(jié)省存儲空間,并且程序便于處理,譬如:
現(xiàn)在,可以考慮更簡單的存儲方式
這表示: 而對于權(quán)限的判斷,則使用存儲的權(quán)限值按位與要進行校權(quán)的值是否等于要進行校權(quán)的值來判斷
于是我們對使用了小技巧的新的權(quán)限基本控制再次進行歸納:
2. 基于角色的基本權(quán)限控制隨著業(yè)務系統(tǒng)的發(fā)展,業(yè)務系統(tǒng)有了第一次升級機會,并附帶了一個新的權(quán)限需求:
按照第一節(jié)的內(nèi)容,這個需求其實不用做任何變化一樣可以滿足,但是問題在于負責授權(quán)的人“太累了”,對于每一個用戶,我們可能都要做一遍授權(quán)的操作。 角色模型設計:
角色表設計Auth_Role:
基于角色的基本權(quán)限控制的原則是:
角色與用戶的抽象關系表現(xiàn)為M-M,這表示:
具體到業(yè)務可以是一個人可以有多個職位;一個職位下有多個人;
假定業(yè)務系統(tǒng)有這樣的職位列表:
假設用戶ID等于1001的用戶職位為總裁兼開發(fā)總監(jiān),那么關系表Auth_UserRole可以存儲為:
業(yè)務約定:總裁有增、刪、改、查四個權(quán)限,開發(fā)總監(jiān)則有增、查兩個權(quán)限,那么關系表Auth_RolePermission可以存儲為:
我們對給予角色的基本權(quán)限控制操作再次歸納為:
3. 基于角色并含有用戶組概念的權(quán)限控制春去秋來,業(yè)務系統(tǒng)迎來了第二次升級機會,并包含以下新的權(quán)限需求:
基于第二節(jié)的系統(tǒng)升級,解決此需求我們會有臨時的做法:做一個角色,給所有開發(fā)崗的同事賦予這個角色。 這樣的臨時做法的確解決了我們的問題,但這里有幾個問題,函待解決:
針對此兩個問題,我們引入一個新的模型:用戶組(UserGroup),用戶組的概念在業(yè)務系統(tǒng)中,可以具體為:部門、小組、團隊等 用戶組模型設計:
用戶組表Auth_UserGroup設計:
基于角色并含有用戶組概念的權(quán)限控制有以下特點:
用戶與用戶組的關系表現(xiàn)為多對多,這表示一個用戶可以屬于多個用戶組,一個用戶組下可以有多個用戶,具體到業(yè)務可以描述為:一個人可以在多個部門,一個部門下可以有多個人; 用戶組與角色的關系表現(xiàn)為多對多,這表示一個用戶組的所有用戶可以擁有相同的多個角色,一個角色下有多個用戶組,具體到業(yè)務可以描述為:同一個部門的人可以擁有多個相同的職位; 為了實現(xiàn)此設計,我們需要做以下新的操作:
假設系統(tǒng)擁有這樣的部門列表:
假設用戶ID為1101的用戶既是前端開發(fā)部的開發(fā)總監(jiān),又是中臺開發(fā)部的開發(fā)總監(jiān);中臺開發(fā)部、前端開發(fā)部的所有同事本質(zhì)都是開發(fā),且所有開發(fā)部的同事都有增、查的權(quán)限,那么: 用戶-用戶組Auth_UserUserGroup關系表可以存儲為:
新增角色:開發(fā)
Auth_RolePermission新增記錄:
Auth_UserGroupRole關系表可以存儲為:
這樣,我們就滿足了本節(jié)提出的需求。 4. RBAC權(quán)限模型現(xiàn)在,系統(tǒng)經(jīng)過3次升級,已經(jīng)有了較為完備的權(quán)限體系,我們解決了大部分問題。 簡單來說,我們的權(quán)限模型設計對于擴展支持不夠 譬如,業(yè)務系統(tǒng)初期對系統(tǒng)的菜單可見性有權(quán)限控制,隨著系統(tǒng)迭代,可能出現(xiàn)對文件的可操作性也需要有權(quán)限控制,這是很正常的事,顯然,依照我們的設計,系統(tǒng)無法滿足。 回顧1、2、3節(jié)的升級內(nèi)容,我們的問題其實是由單一權(quán)限元素變更為多元權(quán)限元素,如果我們能重新將被控制元素變更為單一元素,我們之前的設計則不用變更。 為了解決這個問題,我們對各種權(quán)限元素進行抽象,譬如文件訪問權(quán)限和菜單訪問權(quán)限。抽象為如下圖內(nèi)容: 現(xiàn)在,權(quán)限的Root節(jié)點變成了Permission這個抽象,它沒有具體的意義,但他將各類權(quán)限集中在了一起,使得多種權(quán)限元素重新集中在單一Permission這個抽象元素上,再次揉入到我們的系統(tǒng)中,如下圖: 這就是權(quán)限系統(tǒng)的RBAC完成模型。 至此,借助RBAC模型,我們完成了權(quán)限模塊的理論設計,它能滿足大量權(quán)限控制場景,也是業(yè)界慣用的手段,RBAC模型是一種權(quán)限模型的總結(jié)和歸納,市面上能見到的各種權(quán)限控制,都與RBAC沾邊,也就是說,掌握RBAC,就掌握了閱讀各種系統(tǒng)權(quán)限設計的基礎,有了理論支持。 不過值得注意的是,雖然我們有了理論基礎,但實際應用中,我們還要做一些擴展內(nèi)容。 譬如說權(quán)限歷史,權(quán)限模塊屬于敏感內(nèi)容,是系統(tǒng)的中樞所在,嚴謹?shù)臋?quán)限模塊肯定是不會對操作進行Delete的,而是Fake Delete以保留歷史。上文中這樣的設計為此提供了方便,當用戶的權(quán)限發(fā)生變更時,我們只需要對關系做Fake Delete即可。當然,關系本身需具備IsFakeDeleted屬性。 下一章節(jié)將介紹dotnet core的具體實現(xiàn)。 |
|