企業管理系統前後端分離架構設計 系列一 許可權模型篇

来源:https://www.cnblogs.com/jaycewu/archive/2018/10/22/9833224.html
-Advertisement-
Play Games

前段時間分別用vue和react寫了兩個後臺管理系統的模板 "vue quasar admin" 和 "3YAdmin" 。兩個項目中都實現了基於RBAC的許可權控制。因為本職工作是後端開發,比較清楚許可權控制一個管理系統應該必須具備的核心功能,而且是可以做到通用的。打算寫寫關於管理系統前後端分離方面的 ...


前段時間分別用vue和react寫了兩個後臺管理系統的模板vue-quasar-admin3YAdmin。兩個項目中都實現了基於RBAC的許可權控制。因為本職工作是後端開發,比較清楚許可權控制一個管理系統應該必須具備的核心功能,而且是可以做到通用的。打算寫寫關於管理系統前後端分離方面的文章,也是做一個知識的總結,其中會涉及到vue,react,node,.net core等方面的知識。

術語描述

  • 用戶(Subject):發起操作的主體
  • 對象(Object):指操作所針對的客體對象,比如文章或評論
  • 許可權(Permission):用來指代對某種對象的某一種操作,例如“添加文章的操作”
  • 許可權碼:許可權的代號,例如用“ARTICLE_ADD”來指代“添加文章的操作”許可權

許可權有時候也可以稱為動作或者功能。比如“添加文章”,既可以認為它是一個動作,也可以認為它是一個功能。對象也可以稱為資源。

常用的許可權模型

  • ACL(Access Control List)(訪問控制列表)
  • DAC(Discretionary Access Control)(自主訪問控制)
  • MAC(Mandatory Access Control)(強制訪問控制)
  • RBAC(Role-Based Access Control)(基於角色的訪問控制)
  • ABAC(Attribute-Based Access Control)(基於屬性的訪問控制)

ACL(Access Control List)(訪問控制列表)

ACL是最早也是最基本的一種訪問控制機制,它是用來描述用戶和許可權之間關係的數據列表。它的原理非常簡單:每一項資源,都配有一個列表,這個列表記錄的就是哪些用戶可以對這項資源執行CRUD等操作。當試圖訪問這項資源時,會首先檢查這個列表中是否有關於當前用戶的訪問許可權,從而確定當前用戶可否執行相應的操作。

例如一個文件對象的 ACL 為 Alice: read,write; Bob: read,這代表 Alice 對該文件既能讀又能寫,而 Bob 只能讀取。

由於ACL的簡單性,使得它幾乎不需要任何基礎設施就可以完成訪問控制。但同時它的缺點也是很明顯的,由於需要維護大量的訪問許可權列表,ACL在性能上有明顯的缺陷。另外,對於擁有大量用戶與眾多資源的應用,管理訪問控制列表本身就變成非常繁重的工作。

image

最開始的ACL定義中,用戶直接和許可權掛鉤,數據存儲的是用戶與許可權的關聯關係。如果兩個用戶的許可權是一樣的,那麼就需要分別存儲這兩個用戶與許可權的關聯關係,也是上面所提到的ACL的缺陷。為瞭解決這些問題,便有了對ACL設計的改進,相同許可權的用戶放到同一個分組裡,分組與許可權掛鉤,不再是用戶直接與許可權掛鉤。以及後來出現的RBAC(基於角色的訪問控制),角色與分組也是差不多的概念,角色直接與許可權掛鉤,用戶再與角色進行關聯。

所以,現在一般說ACL,不再是用戶直接和許可權掛鉤的一種許可權控制模型,把它看做一個單純的訪問控制列表即可。列表裡維護的可能是用戶與許可權的關係,也可以是用戶組與許可權的關係,也可以是角色與許可權的關係,甚至是部門,職位等等於許可權的關係。

ACL是許可權體系中的業務規則。RBAC等許可權模型要用到ACL才能工作,ACL服務於RBAC等許可權模型,其它許可權控制體系裡的許可權規則也叫ACL。

DAC(Discretionary Access Control)(自主訪問控制)

系統會識別用戶,然後根據被操作對象(Subject)的許可權控制列表(ACL: Access Control List)或者許可權控制矩陣(ACL: Access Control Matrix)的信息來決定用戶的是否能對其進行哪些操作,例如讀取或修改。
而擁有對象許可權的用戶,又可以將該對象的許可權分配給其他用戶,所以稱之為“自主(Discretionary)”控制。

因為用戶能自主地將自己擁有的許可權授予其他用戶,所以DAC模型可以任意傳遞許可權,用戶能間接獲得本不具有的訪問許可權,因此DAC模型的安全性較低,不能給系統充分的數據保護。

image

DAC可以直接使用ACL的物理模型,區別在於,DAC模型中用戶可以將自己具備的許可權分配給其它用戶(程式里的操作就是根據用戶ID篩選出許可權列表,根據列表為要分配許可權的用戶構造出新的許可權列表並保存)

DAC是傳統的UNIX訪問控制模型,也是Windows文件系統的訪問控制模型。

image

Windows的文件訪問許可權的設置中,除了用戶,還有組。這個組與後面要說到的RABC模型的角色有什麼區別呢?

https://stackoverflow.com/questions/7770728/group-vs-role-any-real-difference

我認為沒必要去劃分的太清楚,不管是組還是角色,都是為了更好的管理和分配許可權在最原始的ACL模型上做的改進。如果有需要,甚至可以把許可權分配到部門,職位上。

MAC(Mandatory Access Control)(強制訪問控制)

MAC是為了彌補DAC許可權控制過於分散的問題而誕生的。在MAC的設計中,每一個對象都有一些許可權標識,每個用戶同樣也會有一些許可權標識,而用戶能否對該對象進行操作取決於雙方的許可權標識的關係,這個限制判斷通常是由系統硬性限制的。訪問時,系統先對用戶的訪問許可級別和資源對象的密級進行比較,再決定用戶是否可以訪問資源對象。用戶不能改變自身和資源對象的安全級別,只有系統管理員或管理程式才能 控制資源對象和用戶的級別。比如在影視作品中我們經常能看到特工在查詢機密文件時,屏幕提示需要“無法訪問,需要一級安全許可”,這個例子中,文件上就有“一級安全許可”的許可權標識,而用戶並不具有。

MAC非常適合機密機構或者其他等級觀念強烈的行業,但對於類似商業服務系統,則因為不夠靈活而不能適用。

MAC可以繼續使用DAC的模型,但是要對用戶進行等級劃分,比如一級,二級,三級。。。,對對象資源也要做劃分,比如機密,秘密和最高機密。用戶訪問的資源的時候,根據用戶等級與資源訪問級別來做判斷,比如一級用戶只能訪問機密文件,如果訪問的是最高機密文件,系統就會拒絕。這一系列規則是優先於DAC的,如果MAC與DAC混用,要先校驗MAC再校驗DAC。

RBAC(Role-Based Access Control)(基於角色的訪問控制)

ACL的訪問控制機制中,直接維護的是用戶與功能的關係,這一系列的關係就是一個許可權列表。當很多的用戶具有相同功能許可權的時候,就要進行繁瑣的關聯操作。RBAC就是在用戶與許可權之間引入了角色的概念。用戶與角色之間做關聯,許可權列表維護的是角色與功能的關係。

image

RBAC是目前使用最普遍的許可權控制模型。當某些用戶具備相同的許可權的時候,只需要為這些用戶建一個角色,把相應的功能關聯到這個角色上,生成角色的許可權列表。當有新的用戶需要相同許可權的時候,把用戶關聯到這個角色上即可。而當用檢查或校驗用戶的操作許可權的時候,查詢用戶所屬角色的許可權列表即可。

當然,RBAC也不是完美的,比如想要為某個用戶單獨設置某個功能許可權,可能需要為這個功能許可權單獨創建一個角色,然後把特定的用戶關聯到這個角色上。當想要移除某個用戶的特定功能許可權的時候,可能需要重新設置角色的功能許可權,把特定功能許可權從當前角色中移除,建立新的角色並關聯特定的功能許可權,然後再把新角色與相關的用戶做關聯(也可以直接在特定功能的程式里校驗操作用戶)

這裡說一個比較常見的RBAC的錯誤的用法:那就是直接使用角色做許可權判斷。比如只有角色A才能做文章的刪除操作。

function delPost(postId){
    if(!isRole('A')){
        return false;
    }
}

如果需求該為角色B也可以刪除文章。那就必須修改代碼

function delPost(postId){
    if(!isRole('A')&&!isRole('B')){
        return false;
    }
}

正確的做法應該是添加"刪除文章"這個功能,把這個功能關聯到相應的角色上。判斷的時候是根據功能去判斷而不是角色。

function delPost(postId){
    if(!hasPermission('POST_DEL')){
        return false;
    }
}

針對“只有角色A才能做文章的刪除操作”這一需求,把這個刪除功能關聯到角色A上,然後把需要這個操作許可權的用戶加入到角色A中即可。當別的角色也需要這個操作許可權,把功能關聯到對應角色上即可,不需要再修改代碼。

在RBAC的核心基礎上,還可以做相應的擴展,比如角色繼承,角色分組之類的,這些擴展都是為了在一定程度簡化許可權管理工作。

ABAC(Attribute-Based Access Control)(基於屬性的許可權控制)

RBAC雖然是目前最普遍的許可權控制模型。但是某些情況下,RBAC是無法滿足並且也實現不了的。比如業務員1和業務員2都屬於業務員角色,都有查看客戶訂單的許可權。當有一個需求,要求業務員1只能查看北京地區的客戶的訂單,業務員2只能查看上海的客戶的訂單。這單單使用RBAC是無法實現。藉助RBAC,可行的做法是,分地區創建角色,然後程式中根據角色做數據的過濾,這種做法缺點之前也提到過,需求變更的時候可能需要每次都修改代碼。

上面業務員查看訂單的例子,地區是訂單的一個屬性,需求就是針對這個地區屬性來做訂單的查詢範圍的許可權控制。這種許可權控制方式就是ABAC(Attribute-Based Access Control)(基於屬性的許可權控制),也被一些人稱為是許可權系統設計的未來。

不同於常見的將用戶通過某種方式關聯到許可權的方式,ABAC則是通過動態計算一個或一組屬性是否滿足某種條件來進行授權判斷的(可以編寫簡單的邏輯)。屬性通常來說分為四類:用戶屬性(如用戶年齡),環境屬性(如當前時間),操作屬性(如讀取)和對象屬性(如一篇文章,又稱資源屬性),所以理論上能夠實現非常靈活的許可權控制,幾乎能滿足所有類型的需求。

例如規則:“允許所有班主任在上課時間自由進出校門”這條規則,其中,“班主任”是用戶的角色屬性,“上課時間”是環境屬性,“進出”是操作屬性,而“校門”就是對象屬性了。

ABAC非常的靈活,但是實現也是非常的難。這其中涉及到邏輯的動態執行,數據動態過濾等,更加具體就是動態拼接SQL語句(使用ORM的話就是動態組裝對應ORM的查詢語句)。

感興趣的可以在Github上搜索ABAC,看看不同語言是否已經有現成的解決方案。下麵說說我學習到的一種實現方式:

還是業務員查看訂單的例子,在RBAC的基礎上,擴展一個實體規則,訂單就是實體,也就是針對訂單設置一系列的規則。規則存儲格式可以是json也可以是xml,甚至是Sql語句,能解析即可。比如北京地區這個規則:

{
    "regionId":1
}

上海地區:

{
    "regionId":3
}

regionId 就是系統里對應區域的Id,也是訂單或訂單相關表的某個欄位。

保存這個規則的時候,規則內容(就是上面的json),規則實體(也就是訂單,表明這個規則是針對訂單的)是必須的。也可以加上這個規則是適用增刪改查中的一種或多種。

創建好實體的規則,將規則與角色做關聯,也就是將北京地區的規則關聯到北京地區角色上,上海地區的規則關聯到上海地區角色上。

後端做許可權校驗的時候,還是先按RBAC模型的控制方式進行校驗(是否具備訂單查看許可權),然後根據當前操作對象(也就是實體),取出用戶所屬角色關聯的對應實體的規則。然後解析規則,動態拼接Sql或者ORM語句。

沒做地區限制(或沒配置規則)的時候,Sql可能是

select userId,orderNo,createdDate from T_Order

配置了規則,解析拼接後可能就是

select userId,orderNo,createdDate from T_Order where regionId=1

這裡是針對地區這個屬性實現了動態的許可權控制。實際開發過程中,要控制的東西是非常多了,查看欄位的控制,數據範圍的控制。要滿足這些複雜的控制,需要制定一套完整的規則,以及針對規則編寫相應的解析程式。比如根據配置的規則,最後解析出來可能是各種Sql語句:<,>,=,like,in,not in等等。

可以看出,要真正的落地實現ABAC是多麼的複雜。每次都要解析規則,對程式的性能也造成的影響,就算使用緩存,命中的概率也是非常的小,因為很多因素都是動態的。

所以,如果需要根據屬性做許可權判斷的場景不是很多的話,還是建議使用RBAC,然後程式中做判斷比較省事省力。

總結

ACL早期定義中是一種許可權控制機制,這種機制直接維護的是用戶與功能的關係,功能就是針對對象定義的一些操作,比如增刪改查的等。用戶與功能的關係列表也稱為許可權列表或訪問控制列表,現在說ACL,一般就是指這個許可權列表或訪問控制列表,但是裡面維護的關係不一定是用戶與功能的關係,在RBAC中維護的就是角色與功能的關係。

RBAC在ACL的基礎上加入了角色的概念,許可權列表或訪問控制列表裡維護的不再是用戶與功能的關係,而是角色與功能的關係。ACL可以和RBAC混著用,既可以在角色上設置許可權,也可以直接給用戶設置許可權,更加靈活。藉助角色的思想,可以在用戶組,組織,職位等等上設置許可權,以便更好的做好許可權管理,也就是將許可權設置從單一個體轉移到某一類組合上。

ABAC非常的靈活,也非常的難實現。

參考文章

許可權系統設計模型分析

Authorization Models: ACL, DAC, MAC, RBAC, ABAC


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文探討如下幾個問題: 什麼是架構屬性 約束和架構屬性的關係 有哪些架構屬性 各個架構屬性涉及知識點 什麼是架構屬性 首先,問個很簡單的問題!請看下麵的Java代碼: 請問上面的代碼中: name和age被稱為Person這個類的什麼? skill又稱為Person這個類的什麼呢? name和age ...
  • 文章提綱 概述要點 理論基礎 詳細步驟 總結 概述要點 理論基礎 詳細步驟 總結 概述要點 設計模式的產生,就是在對開發過程進行不斷的抽象。 我們先看一下之前訪問數據的典型過程。 在Controller中定義一個Context, 例如: private AccountContext db = new ...
  • java併發的一系列框架和技術主要是由java.util.concurrent 包所提供。包下的所有類可以分為如下幾大類: locks部分:顯式鎖(互斥鎖和速寫鎖)相關; atomic部分:原子變數類相關,是構建非阻塞演算法的基礎; executor部分:線程池相關; collections部分:併發 ...
  • 真值和假值 相等操作符(==和 ) 下麵分析一下不同類型的值用相等操作符(==)比較後的結果 toNumber 對不同 類型返回的結果如下: toPrimitive 對不同類型返回的結果如下: 操作符。如果比較的兩個值的類型相同,結果就如下;如果比較的兩個值類型不同,返回的就是false 下麵的例子 ...
  • 關於MVC架構中的Repository模式 關於MVC架構中的Repository模式 關於MVC架構中的Repository模式 關於MVC架構中的Repository模式 個人理解:Repository是一個獨立的層,介於領域層與數據映射層(數據訪問層)之間。它的存在讓領域層感覺不到數據訪問層的 ...
  • 本文長度為3032字,預計讀完需1.1MB流量,建議閱讀8分鐘。 閱讀目錄 為什麼沒有DNS? 如何實施? 優缺點 結語 閱讀目錄 為什麼沒有DNS? 如何實施? 優缺點 結語 為什麼沒有DNS? 如何實施? 優缺點 結語 為什麼沒有DNS? 如何實施? 優缺點 結語 為什麼沒有DNS? 如何實施? ...
  • 領域驅動的火爆程度不用我贅述,但是即便其如此得耳熟能詳,但大多數人對其的認識,還只是停留在知道它的縮寫是DDD,知道它是一種軟體思想,或者知道它和微服務有千絲萬縷的關係。Eric Evans對DDD的詮釋是那麼地惜字如金,而我所認識的領域驅動設計的專家又都是行業中的資深前輩,他們擅長於對軟體設計進行 ...
  • 第三篇這裡嘗試談談緩存的數據分片(Sharding)以及集群(Cluster)相關方案(具體應用依然以Redis 舉例)另見:分散式系統之緩存的微觀應用經驗談(二) 【主從和主備高可用篇】( https://www.cnblogs.com/bsfz/) 一、先分析緩存數據的分片(Sharding) ... ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...