目錄
- 項目核心內容
- 實戰目標
- RGCA 四步架構法
項目核心內容
- 無代碼埋點實現對所有 API Action 訪問控制管理
- 對 EF Core 實體新增、刪除、字段級讀寫控制管理
- 與 Identity 進行融合集成
實戰目標
- RGCA 四步架構法的應用
- 加深對 OPM 和 OPD 的運用
- 為畢業設計打下基礎
RGCA 四步架構法
- Requirement:從利益相關者獲取需求
- Goal:將需求轉化為目標(功能意圖)
- Concept:將目標擴展為完整概念
- Architecture:將概念擴展為架構
從利益相關者獲取需求
- 受益原則
- 痛點
- 利益相關者
- 需求分類、排序、特征
受益原則
好的架構必須使人受益,要想把架構做好,就要專注於功能的涌現,使得系統把它的主要功能通過跨越系統邊界的接口對外展示出來
痛點
對於企業內部的管理系統而言基本上都會有一個權限管理系統,產品經理在進行產品設計的時候需要先確定每一個菜單,每一個按鈕的 key 是什么,再將 key 與權限進行匹配、綁定
但是產品經理無法確定未來所有需要權限管理的地方,所以需要開發人員提前為所有地方設置 key
由於需要設置的 key 有很多,所以可能命名不規范,也有可能會有缺漏,未來涉及到遺漏的地方就需要開發人員重新編碼、發布才能滿足需求,這是開發企業內部權限管理功能的痛點
利益相關者
- 甲方:開發人員,架構師,投資人
- 客戶方:開發人員,產品經理,系統運營人員,老板
受益人 | 需求 |
---|---|
開發者 | 1、集成簡單,少寫代碼;2、功能靈活,可以擴展;3、不要綁死,可以插拔;4、低代碼侵入性,不影響業務代碼 |
產品經理 | 1、隨時可以增加對系統里面功能和數據的權限控制 |
系統管理員 | 1、希望能靈活對系統的權限進行配置,適合角色與員工結構,依照通用行業標准進行配置 |
開發者所屬公司 | 1、低成本(划算);2、不要綁死 |
投資人 | 1、通過該項目的完整演示 RGCA 的架構設計過程;2、將此系統開源回饋到社區,以獲得更多開發者的支持;3、進一步搜集開發者和企業用戶的需求以進行下一步的開發 |
需求分類、排序、特征
提出人 | 分類 | 需求 | 優先級 | 分類 | KANO |
---|---|---|---|---|---|
產品經理 | - | 隨時可以增加對於系統里面功能和數據的權限控制,不需要開發和發布系統 | - | 總體的意願 | 基本型 |
產品經理 | 權限管理 | 可以對功能和頁面進行組合成一個權限給角色,一次配置即可 | 一期 | 必需品 | 基本型 |
產品經理 | 數據權限 | 數據可以控制到新增、刪除、字段級別的修改 | 一期 | 必需品 | 基本型 |
產品經理 | 數據權限 | 可以根據不同的角色、部門、進行查詢數據字段的控制 | 推遲 | 必需品 | 反向型 |
產品經理 | 數據權限 | 可以控制不同的部門、角色查看的數據(比如只能看我所在部門的數據) | 推遲 | 必需品 | 基本型 |
系統管理員 | 權限管理 | 配置方便(使用一定的行業標准進行設計) | - | 必需品 | 無差異型 |
系統管理員 | 功能權限 | 可以對系統內的所有頁面訪問進行權限控制 | 推遲 | 必需品 | 基本型 |
系統管理員 | 功能權限 | 可以對系統內的所有頁面的按鈕進行權限控制 | 推遲 | - | - |
系統管理員 | 功能權限 | 對后台所有API請求進行權限控制 | 一期 | - | - |
開發人員 | 集成 | 集成簡單,少寫代碼 | - | 對缺失物品所表現出來的欲望 | 期望型 |
開發人員 | 集成 | 功能靈活,可擴展 | - | 對缺失物品所表現出來的欲望 | 期望型 |
開發人員 | 集成 | 可插拔 | - | 必需品 | - |
開發人員 | 集成 | 低代碼侵入性,不影響業務代碼 | - | 必需品 | - |
客戶公司高層 | - | 低成本 | - | 總體意願 | - |
客戶公司高層 | - | 可插拔 | - | 對缺失物品所表現出來的欲望 | - |
投資公司 | - | 低成本投入、快速可驗證(敏捷,精益),少走彎路 | - | 總體的意願 | - |
投資公司 | - | 通過該項目的完整演示 RGCA 的架構設計過程(時間為兩天) | - | 必需品 | - |
投資公司 | - | 將此系統開源回饋到社區,以獲得更多開發者的支持 | - | 對缺失物品所表現出來的欲望 | - |
投資公司 | - | 能夠在企業生產系統中使用 | - | 必需品 | - |
將需求轉化為目標(功能意圖)
從系統的頂層角度:定義系統的形式和功能
確定功能意圖(功能意圖是由主要受益者,主要需求而推導出來的)
形式:通用的權限管理系統
to..by..using
為了...通過...使用
功能:無需代碼埋點,通過UI配置改變資源(頁面、按鈕、數據、API)的可訪問性,達到權限控制的目的
過程 + 操作 <= 工具
受益者 | 系統管理員 & 產品經理 |
---|---|
需求? | 對系統中受保護的資源進行權限保護 |
與解決方案無關的操作對象 | 受保護的資源 |
與利益相關的屬性 | 可訪問性,完整性 |
操作數的其他屬性 | 可配置性,可訪問性 |
與解決方案無關的過程 | 攔截/保護 |
無關過程的屬性 | 准確性 |
將目標擴展為完整概念
在目標階段提出了與解決方案無關的過程:攔截,一個模糊抽象的過程,沒有說明由誰來攔截,以什么方式來攔截
與解決方案無關的操作對象:受保護的資源,一個抽象的對象,由需求導出了對象的分類,但是仍然沒有特別具體,沒有具體的場景
到了概念階段需要提出具體解決方案過程:從解決方案不相關,到與解決方案相關
解決方案是幫助我們解決問題的,在目標階段大致定義了需要解決什么問題,功能層面只是說明了產品的優勢
具體的解決方案是在概念階段提出的,它體現出如何把功能進行詳細的描述,所以需要推導到到與解決方案相關的場面
受保護的資源以 API 為例進行推導,定義為 API Action,而攔截在 ASP .NET Core 中表現為 AuthorizationFilter
因為它是一個名詞,不能代表一個過程,所以加上 ing 代表一個過程 AuthorizationFiltering
API Action 經過 AuthorizationFiltering 之后變成一個與解決方案相關的東西
在 ASP .NET Core Mvc 里面變成一個 Result,它是 AuthorizationContext 的一個屬性
Result 有幾種類型:Sucess,Forbiden,Challenge
受保護的資源除了 API Action 之外,還可以是 Entity,而所有 EF 的操作最終都放在 DBContext
DBContext 有一個 SaveChanges 的操作,以及一個 ChangeTracker 的屬性記錄了實體的所有狀態
特化:變得更具體
從受保護的資源到 API Action 就是一個特化的過程,從目標到概念也是一個特化的過程
泛化:變得更抽象
從數據、頁面、按鈕、API 到受保護的資源就是一個泛化的過程
攔截的意圖:保護資源
AuthorizationFilter 在 ASP .NET Core 中只能通過在 Action 上面打標簽 Authorize 的方式進行攔截
這就是所謂的代碼埋點,比如在 entity 上面打標簽也是代碼埋點
攔截的上一層是保護資源,攔截是保護資源的一種方式,需要提前定義受保護的資源
除了受保護的資源,對於所有資源需要動態保護,可以通過動態攔截的方式
動態攔截需要實現一個 DynamicAuthorizationFiltering,不能覆蓋原有的功能
保護資源的上一層是安全,安全除了保護資源,還有很多其他的事情可以做,比如記錄日志
審計日志會記錄用戶的所有訪問記錄,企業可以設置權限
通過這種方式可以不停地將需求往上一層尋找,一直達到最頂層
除了向上之外還可以向下尋找,延伸出整體概念,通過概念片段的組合,構成完整的整體概念
接下來對攔截這一過程進行展開,展開為一組必須得到執行的內部過程,針對每一個內部過程,選用特定的操作數、過程及工具對象對其進行特化,就可以得到相應的概念片段,這也是一個特化的過程
- 配置:系統管理員希望對后台所有 API 請求進行權限控制,所以首先需要知道有哪些 API,對每一個 action 需要可以配置
- 賦權:把角色賦權給用戶
- 認證:用戶認證之后有一個身份
- 授權:基於身份可以進行授權
將概念擴展為架構
- 價值通路與系統架構
- 層級分解
價值通路與系統架構
從資源變成權限,權限綁定給用戶,用戶進行登錄,登錄之后再進行授權
資源分為 ActionAccess 和 EntityAccess
EntityAccess 有 CanCreate,CanDelete,EntityName,Key 幾個屬性,以及每個字段是否允許修改 MemberAccess
同理 ActionAccess 有 Url,Name,DisplayName,Verb 幾個屬性
注冊資源分為 Entity Explorer 和 API Explorer
Entity Explorer 通過 DbContext 進行掃描獲取需要監聽的實體進行注冊
API Explorer 通過 IActionDescriptorCollectionProvider 注冊 Action
授權有一個攔截器 AuthorizeFilter
ASP .NET Core Identity 有一個基於 Claims 的認證授權機制,它是一個 key:value 的數組
Clamis 屬於 User 對象,User 對象屬於 HttpContext
AuthorizeFilter 接收 Claims 和 ActionDescriptior,在 Claims 里面可以獲取到 Action 的信息,所以兩者有關聯關系
對於賦權這一步需要定義權限 Permission 和角色,將權限和角色輸入到賦權,產生一個角色權限 RolePermission
角色權限 RolePermission 是一個組合對象,包含角色與權限
權限和資源之間有一個包含關系,一個權限包含多個資源
至此完成了一條通路:給多個 Action 定義 key 之后,將 key 賦值給角色,角色綁定到用戶,用戶登錄的時候可以獲取到一個 Action 的列表,通過 AuthorizeFilter 來進行對比
授權由 AuthorizationContext 判斷是否有權限
響應分為 API 響應 和 Entity 響應,針對不同的響應有不同的處理方式
對於 API 響應需要判斷是否允許有權限,未認證返回401,無權限返回403
對於 Entity 響應需要 Claims 和 EntityAccessList,通過 Claim 和 AccessList 進行對比
用戶登錄之后得到 User 身份,發起請求產生 ActionRequest
ActionRequest 屬於 HttpContext,最后會輸入到 AuthorizeFilter
整個過程從上到下就是這樣一個價值通路,並且已經包含了形式對象
從資源到權限,角色,再到角色和用戶的綁定,再到授權整個體系,形成了系統架構
層級分解
首先從系統架構中找到實體對象:資源,權限,角色,用戶
資源由 ResourceProvider 提供,分為 ActionResourceProvider 和 EntityResourceProvider
用戶和角色使用 ASP .NET Core Identity 的 UserManager 和 RoleManager
ASP .NET Core Identity 只包含用戶和角色,需要針對 Identity 做擴展,加上權限
UIprotron.Security.Core 負責管理資源和權限
UIprotron.Security.Identity 作為 Identity 的擴展,將資源和權限加入到 Identity 中,相當於一個適配層
UIprotron.Security.ActionAccess 和 UIprotron.Security.EntityAccess 分別負責 Action 和 Entity 的權限
大體上分為以下幾部分:
- ASP .NET Core Identity:用戶認證的庫
- UIprotron.Security.Identity:Core 與 Identity 的集成組件
- UIprotron.Security.Core:對資源和權限的管理
- UIprotron.Security.ActionAccess:Action 資源發現和權限控制
- UIprotron.Security.EntityAccess:Entity 資源發現和權限控制
- UIprotron.Security.Store.EntityFramework:資源和權限的 EF Core 持久層
洋蔥架構
- CoreAdapters:最核心最穩定的放最里面
- Application Security.Identity:應用層,Identity 的擴展
- Action Access
- Entity Access
- EfResourceStore
對每一層進行拆分,將功能拆分為 Core,Models,Store 和 EFStore
課程鏈接
https://appsqsyiqlk5791.h5.xiaoeknow.com/v1/course/video/v_5f39bdb8e4b01187873136cf?type=2
本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。
歡迎轉載、使用、重新發布,但務必保留文章署名 鄭子銘 (包含鏈接: http://www.cnblogs.com/MingsonZheng/ ),不得用於商業目的,基於本文修改后的作品務必以相同的許可發布。
如有任何疑問,請與我聯系 (MingsonZheng@outlook.com) 。