由淺入深,聊聊許可權設計
作者:cross___
鏈接:
https://my.oschina.net/cloudcross/blog/1920706
轉載請在文中註明來源和作者
許可權設計的雜談
這篇文章的定位,不是宣傳某個框架,僅僅之是梳理一下有關許可權方面的一些想法和最近項目中的一些探索過程。 我們主要想解決一下問題。
什麼是許可權,程序員理解的許可權和客戶所理解的許可權是不是一致的。
許可權的劃分原則,許可權到底是根據什麼原則進行組合的。
角色是用戶與許可權之間的必要的關係嗎?角色到底承接了什麼作用。
如何進行合理的表設計。
安全框架。
1.什麼是許可權
在很多與開發者也好,與客戶也好,溝通的過程中我們很多次提到了許可權,但是許可權具體的含義每個人理解的含義都不明確,這樣很容易造成雙方信息不對稱,有的人就只是把許可權理解成某個頁面的是否可訪問,但是有的人卻理解成其他的東西。所以我們要徹底的定義一下許可權是什麼。
許可權到底是名詞屬性還是動詞屬性,還是名詞、動詞屬性均包含,這對於許可權的含義很重要。如果是名詞屬性的話,那麼它應該是有具體的指代物;如果是動詞,則應該具有行為表示。
許可權的名詞屬性:api介面、頁面、功能點。
許可權的動詞屬性:可操作、不可操作。
那麼我們現在來看,其實許可權是名詞、動詞屬性,它一定是表達了兩層含義。即控制的對象、操作。
例如:許可權A表示頁面A的可訪問。
例如:許可權B表示頁面B可訪問且頁面內的功能b不可使用
例如:許可權C表示介面C不可調用。
例如:許可權D表示頁面D可訪問,且介面D可訪問。
那麼進一步的說明,許可權可以表示單個控制的對象的操作集合,也可以表示多個控制的對象的操作集合。而這兩者的取捨則是有設計人員決定的。
一句話總結許可權的含義:what(若干元素)進行how(若干操作)
2.許可權的劃分原則
我們了解了許可權的具體含義之後,接下來就是用的問題,我們該如何去使用許可權,如何將系統中的操作元素進行一個組合,這個我借鑒網上的一篇文章來解釋。劃分原則可以按照「最小特權原則」和「數據抽象原則」。
最小特權原則
我先舉一個反例,我把系統中所有的元素和操作都組合成一個許可權。一個用戶擁有這個許可權就相當擁有了系統所有的功能,實際上這肯定是不行的,用戶在一套系統中一定有他不允許操作的內容,哪怕是超級管理員也可能會有不能操作的元素,那麼最大化許可權則是行不通,因為不符合常理。
據此,我們就把許可權再進行一個拆分,按照業務模塊進行拆分,但是這實際上也是不行的。就比如系統中的財務模塊,假定模塊中含有報銷頁面和申報頁面,如果按照模塊進行拆分,那麼肯定有用戶同時包含了兩個互斥功能。
根據1和2,我們需要按照最小化進行許可權劃分。但是這個也是值得商榷的,因為不同系統,最小的許可權劃分對於提供的功能來說,劃分的角度也是不同的。
數據抽象原則
「最小特權劃分」從某個程度上來說決定了控制的對象 ,而數據抽象原則是是決定了操作。
數據抽象從字面的意思來看,其實很難理解到底是什麼意思。通常我們口頭上說最多的是CRUD增刪查改,這實際上就是數據抽象的一種,我們可以理解成元素操作許可權的意思。
但是CRUD並不是數據抽象的全部,增刪查改用於單實體,基本是沒問題的,但是在構建關係上,其實是不夠用的,例如任免某個經理管轄某個部門,從業務表面而言它修改了經理的管轄範圍。但是從代碼底層構建上來說,它屬於在經理和部門間新增了一道關係,所以根據需求我們需要再額外的增加一類許可權「任免許可」,這一類型的擴展則需要根據系統實際的業務情況進行劃分。
「最小特權」和「數據抽象」分別決定了許可權中控制的對象和操作,但是這裡面還差了一個角度,則是現階段非常普遍的前後端分離的許可權劃分的問題。
服務端的許可權
前後端分離下的服務端,本質而言只是提供介面的或者rpc服務等其他資源服務的服務提供方。
服務端能提供的許可權的鑒權機制的對象:介面服務(api或者其他形式的服務)不包含前端的頁面或頁面中的功能點。
前端或移動端的頁面元素的控制和鑒權實質上不由服務端控制。
服務端可以單獨的控制服務的許可權。
服務端的服務對象是前端、移動端、第三方客戶端,提供的服務是介面服務。
在前後端已經分離的情況下,服務端對於前端而言只是介面的提供者,但無權干涉前端頁面的展示,服務端對於前端而言,能提供的是僅鑒權服務的介面而已,但是頁面的構成,頁面的欄目菜單或頁面內的功能點的構成均由前端單獨完成的。
前端或移動端的許可權
前端的鑒權包含頁面的可訪問,和頁面上的某項功能按鈕是否可以操作。
前端和移動端的服務對象是用戶,提供的服務是可視化的頁面。
前後端的服務對象的責任劃分清晰之後,我們就不會混雜許可權的歸屬的問題,在過去前後端沒分離的情況下,頁面本身就是服務端的一體,就沒有這方面的問題。雖然分清楚了各端本質提供的服務的情況,但是前後端分離的許可權劃分中仍有新的問題。
因為服務端和前端的鑒權對象不一致,服務端只能鑒權到api介面,那麼是否將api介面和前端的頁面乃至頁面功能點進行資料庫表與表層面的綁定關係。
如果進行了進行了表與表之間的綁定關係,那麼整個許可權系統的維護量,是否能在能承受範圍之內。
如果不進行表與表之間的綁定關係,前端頁面在操作功能的時候,服務端如何鑒權頁面調用的api介面是否在用戶可操作的許可權之內?
其實上面的問題則需要一個取捨,要麼增加運維成本嚴格控制前端調用api介面的關係,偏重服務端的介面服務鑒權。要麼是給api介面和前端頁面及功能點再提供一個通性的邏輯判斷處理,如:頁面及調用的功能點屬於某個業務模塊的操作許可,而頁面觸發的介面也剛好是這個業務模塊的操作許可,那麼鑒權通過,否則鑒權失敗。這種就是屬於側重前端對於用戶的控制,弱化了介面級的控制。
3.角色與許可權的關係
通過1,2的描述,基本確定了許可權的定義和劃分一個許可權的通用法則。用戶在系統中最終是通過許可權來使用各種功能點,是否有必要在用戶和許可權中間再額外的附加一個關係。在我們現在的許可權設計中,是增加了這樣一層關係的,就是角色。
減少操作層面的重複性。角色其實就是一組許可權的集合,是許可權集合的更高級抽象,為了便於運維和實際管理,通過角色的賦予,替代了許可權賦予用戶的繁瑣性,在一套系統中,普遍情況都是許可權的數量多於角色的數量。
許可權是控制對象和操作集合,它本身不存在任何狀態,但是在賦予在用戶身上則擁有了狀態,比如許可權A中允許用戶訪問頁面A,許可權B允許用戶訪問頁面B,許可權D運行用戶訪問B頁面,但是不允許訪問A頁面。那麼這層關係的維護在角色層面的話,會更加清晰,也就是說本身角色具有許可權集合組裝的策略問題,對於互斥的許可權有不同的方案處理。(許可權中沒有某個操作和許可權中禁止某個操作,是兩個不同的角度,不能混為一談)
因為許可權的可能存在互斥性,在實際業務中也會引發角色的互斥性,舉一個現實中的案例來解釋互斥性:張三是軟體部的負責人但因為工作的特殊性也同樣隸屬於業務部的普通員工,我們設定負責人是可以要求人事部門給本部門進行招聘的,在實際的情況中,張三能給軟體部招聘新員工,但是不能給業務部招聘員工。我們把這個案例運用在系統中,張三則是擁有負責人和普通員工兩個角色,但是招聘的功能如果不加以控制,則會發生張三給業務部招人的結果。於是為了解決角色的這類問題,引入了職責劃分的方案。
職責劃分分為:靜態、動態。所謂靜態職責劃分則是在角色創建之初就已經確定了角色的職責內容。動態職責劃分是系統運行過程中對用戶已有的角色進行控制,例如:某些角色不能共存在用戶身上(互斥)、角色或角色的分配數量限定(控制用量)、角色與角色同時只能激活一個進行使用(時刻唯一)。
引入角色的概念後,實際上這已經是一個比較完整的RBAC的許可權設計的模型了。
4.數據表的設計思路
根據3的結論,實質上已經有了一個基礎的表設計的雛形。在這裡就有一些值得注意的點。
(1)問:許可權表是否有必要存在?
(1)答:這個要結合系統的實際使用場景進行考慮,如果系統中的許可權的對象很單一,比如只有頁面,或者只有api介面的話,其實許可權表可有可無。增加許可權表反而會導致初始化項目許可權的工作量增加。但是若系統中的許可權對象是多個,那麼許可權表的存在就有了更深層次的意義。在許可權對象是多個的情況,許可權表的存在就是為了更好更抽象的組合「最小特權」及「責任劃分」的操作對象。同時,一旦系統中的操作對象增加了,只需要給許可權表增加一個對象表和關係表就可以了。這樣易於擴展。
(2)問:api介面和頁面實際上是沒有關係的,但是在鑒權活動是有關係的,頁面若和api沒有一點綁定聯繫的話,服務端介面調用的時候則要麼攔截掉所有指定的介面(頁面和api介面沒綁定的話,則頁面的介面調用都不能成功),服務端介面完全不攔截介面,也會不安全,但是api介面和頁面功能在表結構層面的綁定會產生運維的大量工作成本,如何更好的設計。
(2)答:在許可權如何劃分中已經提過了這一點,在表結構中,我們可以增加一張業務模塊表和操作表(也可以在數據字典表中增加這兩類數據),我們可以在頁面和功能點鐘 綁定業務模塊和操作表關係,在api介面的代碼層面去綁定業務模塊和操作,在邏輯上綁定關係,解耦表結構之間的關係,那麼可以在一定程度上解決這一點,這樣做只會出現一種問題,那就是用戶訪問頁面的時候可調用的api介面會比實際可調用的介面數要多,但是前端許可權管理會隱藏功能點,這樣就在可視化的程度上解決了這個問題。
5.安全框架
由於我們是基於RBAC的許可權設計,現行java框架下最常見的就是shiro和Spring Security 。這兩個就是仁者見仁智者見智了,我兩者都實用過。僅建議使用shiro的話,可以更好的理解RBAC的設計思路,Spring Security 也是個不錯的框架,但是它涉及到的概念太多,並不利於初學者去了解最基本的許可權設計。我在這隻在學習的角度上去比較這兩個框架,並沒有再其他領域去做比較,也不去比較。
引用的文章
許可權系統與RBAC模型概述[絕對經典]
https://blog.csdn.net/yangwenxue_admin/article/details/73936803
TAG:代碼技巧 |