.NET 雲原生架構師訓練營(許可權系統 RGCA 架構設計)--學習筆記

MingsonZheng發表於2022-01-19

目錄

  • 專案核心內容
  • 實戰目標
  • 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) 。

相關文章