權限相關

在許多的實際應用中,不只是要求用戶簡單地進行註冊登錄,還要求不同類別的用戶對資源有不同的操作權限。目前,權限管理系統也是重複開發率最高的模塊之一。

ITeye論壇中關於權限控制的帖子非常之精彩,現將其精華內容摘錄於下。

樓主關於權限控制的問題 Top

關於權限控制的討論源於guoyong123的一個問題:
guoyong123 寫道
權限控制應該是分爲3類:

1. 菜單級別
2. 頁面元素級別
3. 數據級別

目前好像用的比較多的是基於RBAC的,我經常用的也就是控制到菜單級別,對於控制頁面元素和數據級別用的不是很多,目前需要解決權限控制到頁面元素級別,網上看了很多但是不是很明白。不知大家有什麼好的解決方案沒有。大家的表都是怎樣設計的?希望高手們不吝指點,有什麼好的方案讓借鑑借鑑。

我的目前表主要就包括5張:

用戶表;角色表;菜單表(包括一級菜單、二級菜單) ;用戶和角色的關聯表(用戶角色多對多);角色和菜單的關聯表等。

RBAC(基於角色的訪問控制)掃盲貼 Top


RBAC(Role-Based Access Control,基於角色的訪問控制),就是用戶通過角色與權限進行關聯。簡單地說,一個用戶擁有若干角色,每一個角色擁有若干權限。這樣,就構造成“用戶-角色-權限”的授權模型。在這種模型中,用戶與角色之間,角色與權限之間,一般者是多對多的關係。(如下圖)


角色是什麼?可以理解爲一定數量的權限的集合,權限的載體。例如:一個論壇系統,“超級管理員”、“版主”都是角色。版主可管理版內的帖子、可管理版內的用戶等,這些是權限。要給某個用戶授予這些權限,不需要直接將權限授予用戶,可將“版主”這個角色賦予該用戶。

當用戶的數量非常大時,要給系統每個用戶逐一授權(授角色),是件非常煩瑣的事情。這時,就需要給用戶分組,每個用戶組內有多個用戶。除了可給用戶授權外,還可以給用戶組授權。這樣一來,用戶擁有的所有權限,就是用戶個人擁有的權限與該用戶所在用戶組擁有的權限之和。(下圖爲用戶組、用戶與角色三者的關聯關係)
在應用系統中,權限表現成什麼?對功能模塊的操作,對上傳文件的刪改,菜單的訪問,甚至頁面上某個按鈕、某個圖片的可見性控制,都可屬於權限的範疇。有些權限設計,會把功能操作作爲一類,而把文件、菜單、頁面元素等作爲另一類,這樣構成“用戶-角色-權限-資源”的授權模型。而在做數據表建模時,可把功能操作和資源統一管理,也就是都直接與權限表進行關聯,這樣可能更具便捷性和易擴展性。(見下圖)


請留意權限表中有一列“權限類型”,我們根據它的取值來區分是哪一類權限,如“MENU”表示菜單的訪問權限、“OPERATION”表示功能模塊的操作權限、“FILE”表示文件的修改權限、“ELEMENT”表示頁面元素的可見性控制等。

這樣設計的好處有二。其一,不需要區分哪些是權限操作,哪些是資源,(實際上,有時候也不好區分,如菜單,把它理解爲資源呢還是功能模塊權限呢?)。其二,方便擴展,當系統要對新的東西進行權限控制時,我只需要建立一個新的關聯表“權限XX關聯表”,並確定這類權限的權限類型字符串。

這裏要注意的是,權限表與權限菜單關聯表、權限菜單關聯表與菜單表都是一對一的關係。(文件、頁面權限點、功能操作等同理)。也就是每添加一個菜單,就得同時往這三個表中各插入一條記錄。這樣,可以不需要權限菜單關聯表,讓權限表與菜單表直接關聯,此時,須在權限表中新增一列用來保存菜單的ID,權限表通過“權限類型”和這個ID來區分是種類型下的哪條記錄。

到這裏,RBAC權限模型的擴展模型的完整設計圖如下:


隨着系統的日益龐大,爲了方便管理,可引入角色組對角色進行分類管理,跟用戶組不同,角色組不參與授權。例如:某電網系統的權限管理模塊中,角色就是掛在區局下,而區局在這裏可當作角色組,它不參於權限分配。另外,爲方便上面各主表自身的管理與查找,可採用樹型結構,如菜單樹、功能樹等,當然這些可不需要參於權限分配。

以上,是從基本的RBAC模型進行了擴展,具體的設計要根據項目業務的需要作調整。歡迎大家提出批評意見!

george_space的“權限控制”的部分數據模型 Top

 

有時候需要單獨爲一個用戶增加一兩個權限的,這時候單獨爲這個用戶設計一個“角色”,不值得,所以我設計的是:既可以通過角色爲用戶分配權限,也可以直接將權限分配給用戶。

--------------------------------------------

我接觸過的幾個開發人員,都不明白爲什麼要直接給用戶分配權限,但是在軟件的實際應用中,如果完全基於“角色”爲人員分配權限,你會 發現角色之間重複、冗餘的權限很多,這樣反覆的定義多種多樣的“角色”,還不如設計成可以直接爲人員分配權限呢。

--------------------------------------------

權限管理基本上分爲以下幾個步驟:

 

1、定義權限-》定義角色-》爲人員分配角色(或者直接分配權限),這是一個分配權限的過程;

--------------------------------------------

2、定義受保護資源-》爲“受保護資源”指定授權權限,這是一個授權的過程;

--------------------------------------------

3、應用程序請求“受保護資源”-》“受保護資源”的授權權限與人員持有的權限進行匹配-》匹配成功,允許訪問資源,匹配失敗,不允許訪問資源,這是一個認證的過程。

--------------------------------------------

上面這三個過程,是典型的“操作權限”的流程。

--------------------------------------------

關於“頁面元素”的控制,目前多數權限管理系統,都是用“自定義權限標籤”來控制頁面元素的顯示與否的。

 

我目前也是這樣實現的,但是我一直認爲:其實用“自定義權限標籤”來控制頁面元素的顯示與否,跟直接在視圖中使用程序邏輯判斷,是一樣的,並沒有做到“靈活配置”,當權限編碼改變,或者權限含義改變時,還是要去動頁面的標籤,所以跟寫死沒什麼分別。

 

如果頁面元素是通過服務端組裝成json,或者別的格式的數據,然後返回到視圖層進行渲染,這樣的話,就可以做到“頁面元素的權限靈活配置了”,可以通過數據庫定義那些按鈕對那些權限或角色進行顯示。

 

“服務端組裝視圖層組件,返回視圖層渲染”,這個模式雖然做到了“對頁面元素的權限靈活配置”,但是犧牲掉了很多東西,比如加大了服務端的複雜度,使得頁面的設計更加“程序員化”,而不是“美工化”等。

--------------------------------------------

至於最關鍵的“數據權限”,也就是人員對數據的讀取深度的控制,是更爲複雜的流程。

--------------------------------------------

對於“數據深度”的控制,我目前的做法是和業務結合的非常緊密,即:在讀取數據的程序中,比如“列表”頁,首先判斷當前登陸者有沒有“讀取任意深度的權限”,如果有,就不做讀取限制;如果沒有,則判斷當前登錄人員是不是部門主管,如果是,則遞歸讀取本部門下的所有數據,如果不是主管,則只讀取自己的數據。

--------------------------------------------

“數據深度”的控制,細設計的話,應該可以更通用,更靈活,大家有什麼更好的思路,可以討論一下。

--------------------------------------------

我目前設計的是一個人員只能有一個“角色”,當然,如果設計成一個人員有多個“角色”,也不是很複雜的事情,在“用戶表”和“角色表”之間增加一個“用戶-角色映射表”就可以了,但是爲了系統的簡單起見,我把這種設計簡化了。

--------------------------------------------

以下是我的“權限控制”的部分數據模型:


 

 

我目前比較關心的是:

 

1、數據權限(讀取數據的深度)有什麼更通用的設計?

2、頁面元素的控制,除了使用“自定義權限標籤”,或者“服務端組裝視圖層組件”兩種方法,還有沒有更好的設計?

 

sdnasky和george_space關於該問題的精彩探討 Top

sdnasky 寫道
數據模型不是關鍵,只要保存用戶-權限關係就行了

設計上的關鍵是找到權限控制點

界面級:自定義標籤可以實現

URL級:Filter可以實現

後臺方法級:AOP可以實現

數據級:良好設計+AOP可以實現

即使沒有良好的設計,針對不同需求,在控制點寫攔截處理類就行了,只是重複代碼的問題

權限的關鍵是:找到控制點,攔截,然後做你想做的事情


george_space 寫道

• sdnasky寫到:
• 界面級:自定義標籤可以實現
我現在也是使用自定義標籤來實現的界面元素控制:

Html代碼 複製代碼
  1. <eagle:hasPermission name="saveOrder">      
  2.   
  3.     <input type="image" src="${rootUriOfCurrentPage}/resources/image/button/save-order.png" name="submit_top_button" id="submit_top_button" value="保存訂單" />     
  4.   
  5. </eagle:hasPermission>    


問題:現在標籤中定義擁有“saveOrder”權限的人,可以看見保存訂單的按鈕,但是項目交給客戶以後,客戶想讓擁有“kissGirl”權限的人,也能看見保存訂單按鈕,那麼你是不是要去修改頁面?

這樣每次權限定義發生變動,都要去修改頁面自定義標籤,跟硬編碼寫死權限判斷有什麼分別?

• sdnasky寫到:
• 數據級:良好設計+AOP可以實現
問題:怎麼實現?這個是關鍵!

舉個簡單的例子:

一個列表頁,要求:普通員工看見自己發表的信息(標題、發佈時間);

部門經理看見本部門的信息(標題、發佈時間 + 發佈人積分);

管理員看見所有的信息(標題、發佈時間、發佈人積分 + 刪除/修改)按鈕。

這個列表頁是使用web service從美國加利福尼亞州總部讀取的,問,如何實現數據權限控制?

這樣的需求,不是一個小小的AOP攔截就能夠搞定的,即使能搞定,其複雜度也是超乎想象的。

有一個比較笨的方法,就是在服務端做權限邏輯判斷,組裝出當前權限應該看到的數據量和數據列,然後使用json

格式傳遞到視圖層進行渲染,這樣就相當於把視圖端自定義標籤所做的判斷,移動到了服務端。

服務端使用策略模式,針對不同的權限,執行不同的查詢邏輯;

如果有新的查詢邏輯出來,就更麻煩了,理論上可以使用“頁面上可視化配置 = > 動態生成java類 => 動態加載新的查詢邏輯類 => 動態執行新的查詢邏輯類”這樣的方式來把新邏輯插入當前的判斷中,但是這僅僅是理論上的設計,實際做起來,可不是上面這樣三言兩語能夠“說”完的。

要做到數據權限的精確控制,除了和系統緊密耦合的做法和硬編碼判斷的做法,我還沒有發現更好的實現,請樓下大牛們趕緊賜教。



sdnasky 寫道
1.標籤使用錯誤,界面標籤只是標識出該控制點的唯一標識,剩下的事情由標籤處理函數去取出用戶權限列表,並且判斷用戶是否含有該權限點的唯一標識

Html代碼 複製代碼
  1. <eagle:hasPermission id="xxx.jsp.saveorder">    
  2.   
  3.     <input type="image" src="${rootUriOfCurrentPage}/resources/image/button/save-order.png" name="submit_top_button" id="submit_top_button" value="保存訂單" />    
  4.   
  5. </eagle:hasPermission>   


權限標識可以使用命名規則,用來區分不同類型權限:菜單,界面控件,或其他的

2.取數據的方法如果設計合理,預留了可以方便添加數據過濾的接口,用AOP攔截方法調用,修改輸入參數即可

即使設計不好,用AOP攔截方法調用(不調用現有方法),直接調用全新的含有數據過濾的取數據方法即可,無非是有重複代碼而已

補充一句不是“小小的AOP” AOP是非常強大的,它是代理模式,既然都給我代理,我就可以爲所欲爲(攔截調用,修改參數,修改返回值,甚至調用全新的方法),都爲所欲爲了,還不夠強大麼?



george_space 寫道
1、我的權限標籤支持ant式過濾的,類似下面:

Html代碼  

Html代碼 複製代碼
  1. <eagle:hasPermission id="user.customer.*,user.manager.*">      
  2.   
  3.     <input type="image" src="${rootUriOfCurrentPage}/resources/image/button/save-order.png" name="submit_top_button" id="submit_top_button" value="保存訂單" />     
  4.   
  5. </eagle:hasPermission>    


但是問題的關鍵是:如果現在客戶要求“user.teamleader.*”也能保存訂單,你是不是要把“user.teamleader.*”手動添加到權限標籤裏面去?是不是要改動視圖層頁面?是不是跟修改硬編碼也簡單不到哪裏去?

2、AOP方式沒有親身實踐過,不知道是否行得通,不做評論。

下面是我現在的初步設計,總體的意圖是將查詢邏輯留給軟件部署者來在界面中配置:



執行階段時序圖:




sdnasky 寫道
實際解決上述兩個case

1. 頁面標識出該頁面保存按鈕權限id爲xxx.jsp.saveorder,誰擁有這個標識誰就能訪問,“擁有“saveOrder”權限的人”和“擁有“kissGirl”權限的人”都是角色,都不是最細緻的針對唯一權限標識點,不管你用什麼數據模型,找到 用戶-權限唯一標識 關係即可

2.如果美國總部“設計良好”提供了方便添加過濾條件的參數,AOP攔截調用修改傳入參數即可,即使美國總部是豬,沒關係,AOP獲得返回結果,針對返回結果編寫處理類,然後將處理之後的結果返回即可,至於界面上的“刪除/修改 按鈕”,留給界面級權限模塊處理,同上甚至有跟多要求,針對每一條數據處理都不一樣,比如張山可以“刪除/修改 按鈕”135條,李四可以“刪除/修改 按鈕”2468條,都沒問題,權限標識

xxx.jsp.deleteupdate.1
xxx.jsp.deleteupdate.2
xxx.jsp.deleteupdate.3
xxx.jsp.deleteupdate.4
xxx.jsp.deleteupdate.5
...

標識後接上ID即可,至於處理標籤如何處理,根據規則來就行了

最後共享一個這邊的權限設計

其他數據模型不看了

權限表含有3個字段

expression 可以爲空,該權限控制點的處理表達式
script     可以爲空,該權限控制點的處理表腳本
handle     可以爲空,該權限控制點的處理表類

系統需要引入腳本引擎,我們這裏用的是jbpm的腳本引擎,最後搞不定就只有反射處理類出馬了,不要指望用戶直接寫腳本,用戶最多自己寫簡單expression 什麼 money>10000 , level=經理 啥的,如果用戶有特殊需求,根據情況,我們寫好script或者handle提供用戶下拉選擇,填寫參數。

george_space, 關鍵是你們的權限標籤保存的不是權限點,而是角色,因此沒轍

權限標籤就是標識出,這塊範圍的權限標識就可以了,權限點跟角色的關係交給數據庫動態處理就行了

至於有無權限的判定處理,默認處理,表達式,腳本,處理類,各種工具提供選擇


george_space 寫道
我的權限標籤,既可以制定一個或若干個權限,或者使用 user.*這樣的ant通配符,

也可以制定一個或若干個角色,或者使用role.*這樣的ant通配符,

我的權限系統是我自己設計的,因此不存在受制於人不便修改的問題。

如果有更好的實現方式,我很樂意及時來改進,關鍵是到現在爲止,我還沒發現比我的權限標籤更通用,更智能的“新標籤方式”

使用標籤方式控制頁面元素,本身就是一種硬編碼的變通寫法,如果再使用標籤來控制列表頁的列數量,那簡直就是硬編碼中的戰鬥硬,金剛石中的硬鑽頭,硬到無地自容了,沒有任何通用性可言。

使用權限標籤來定義頁面元素的顯示、隱藏,定義列表頁的列數量,這樣的做法只能適用於項目型軟件,不適用或者說不能完全適用於產品型軟件。

你說的標籤方式我理解,就是:

標籤定義一個ID="helloGirl"  => 標籤實現類中判斷當前登錄者的權限列表,遍歷權限所管轄的所有頁面元素ID,看看是否包含本標籤的ID:helloGirl => 如果包含,顯示標籤body,如果不包含,不顯示標籤body

是不是這個意思?


sdnasky 寫道
是的,不過"helloGirl"容易引起歧義,我們的做法是命名規則 頁面.模塊.控件

如果權限id爲 xxx.jsp.xx.btnSave,你看不就解決了你的問題了麼

通配符應該作爲角色-權限關係存於數據庫,你們的問題就是由於通配符引起的,一個點就是一個點,要1對多就用數據庫存關係

爲什麼自定義權限標籤無法控制列?當然可以啦

每個列一個權限標識,有標識,顯示,沒有標識忽略

權限標籤加在populate單元格上

其他ITeye會員關於此問題的回覆 Top

sunway00 寫道
多角色的情況一般來說是很普遍的,很難將每一個用戶的功能都抽象爲角色進行單一的角色賦權。給給用戶單獨賦予權限是一種變通的解決辦法,但是一不小很容易失控造成角色和權限的混亂。

數據權限如果有兩個或更多維度的話應該如何處理呢?

比如:分地區、類型兩種維度

省日化經理只能看本省範圍內日化產品的銷售情況,城市經理能看到本市範圍全部商品的銷售情況等等

如果不同的角色對於同一個功能有不同的數據範圍要求,如何能設計一個良好的通用模型?


sslaowan 寫道
數據包括業務對象,菜單,功能這些東西都是ACL,一張表搞定,這就是一個通用模型了。

然後用戶角色就是RBAC,可以爲不同用戶分組形成UserGroup,可以爲不同權限分組形成Role

不懂的話可以參考Spring Security的實現。


四書五經 寫道
樓主可有接觸過微軟的WSS(現在叫MOSS),它裏面的權限管理非常的棒:網站級的、頁面級的、菜單級的、內容級的(就是一個簡單的word文件都可以賦權限給不同的用戶來操作)

、用戶組級的、域級別的...總之很多。

完全基於數據庫實現,有興趣的話自己找找wss/moss權限管理的文章看看


a123159521 寫道
RBAC,經典模型!,可以在此基礎上進行擴展,比如權限分爲菜單權限,頁面元素權限,資源權限,萬變不離其宗


poko123 寫道
動態權限 是難上加難啊,放在持久層 牽涉的也太多了。

到現在爲止我也沒辦法解決。不放持久層分頁就會有多有少,要是少到一條都沒有就麻煩了。有一點的話 還糊弄的過去。

其他層次的問題 , 我全部通過AOP 攔截。有時候還要修改攔截的數據,反正搞的權限代碼也得理解業務,都不完美。


vb2005xu 寫道
我覺得完全可以綜合成 [資源] - [角色] - [用戶]

只是資源裏面的 可以多加一個 type 字段 類型可以是 url ,file 等

這樣會不會簡化了呢

前天一想寫這個玩意 ... 鬱悶 http://vb2005xu.iteye.com/blog/1136852

發現角色之間重複、冗餘的權限很多

關於這個 我說說我的解決方案 roles 表裏面加個 字段 parent_id 以此來實現 角色間的繼承


yin_bp 寫道
權限管理可以總結爲以下幾點:

1.權限模型選型-基於角色控制的權限模型,組織機構模型等等

2.權限信息維護-尤其是分級權限管理和維護,這個很重要,要做到不失功能的前提下,儘量做的簡單實用、切忌複雜化,還要有強大的權限查詢和回收功能

3.權限控制api-這個一定要通俗易懂,而且要保證性能,可適當引入緩衝機制

4.權限緩衝同步和刷新-尤其是在集羣環境下

5.做到以上幾點的前提下,功能級權限和數據級權限就沒有問題了,爲了降低權限表的數據量,可以在通用權限維護管理的前提下增加按類別劃分存放權限數據表的功能

至於權限的劃分,應該可以劃分爲以下三大類:

1.功能權限-系統菜單,頁面功能操作點

2.數據權限-業務數據範圍權限

3.管理權限-管理功能權限和數據權限的權限


Metadmin 寫道
數據級應該使用規則引擎來實現;

推薦一款開源產品——ralasafe權限管理中間件,內部也是使用規則對數據級策略進行描述。ralasafe還提供了圖形界面來實現規則的圖形化配置,不必手寫配置。

http://www.ralasafe.cn


owenludong 寫道
頁面標籤上的ID 當然需要用權限ID,像你得需求 如果要給另外一個用戶使用那麼我們就把該權限付給該用戶即可,標籤實現類裏 只要根據權限ID 去查找該權限ID對應的用戶,只要有當前用戶 就可以顯示。

但是這裏還是又一個問題。就是這樣做違背了RBAC的模型,我引用了ralasafe權限中間件其中一位commiter的話:“主體和資源種類很多時候,權限控制條目則急劇膨脹條目是N(主體)*N(資源),顯然需要有針對性的尋找規律進行分解從而減少數目,可以發現的是如果通過定義有限的角色(R)來替代主體授權則條目數量變化爲N*R+R*M,顯然角色數量是遠遠小於主體數量的,從而能夠達到簡化的母的。這就是RBAC得來源”。因此把上面的用戶全部換成角色,基於角色的訪問控制將很好的防止了權限的冗餘  後期維護也方便。 所以基於頁面級的權限控制 我們建議將控制點設置爲權限ID或叫資源ID,george_space提出的基於規則的命名 這個後期維護起來將會省很大的力氣,另外實現類 就根據權限ID去role_privilege表裏查找所有的角色,遍歷該角色 查找上下文中用戶是否在這些角色中。 ralasafe嚴格按照RBAC模型 並基於策略的模型實現數據集權限。 網址:www.ralasafe.cn  共同關注。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章