.NET 云原生架构师训练营(权限系统 RGCA 架构设计)–学习笔记

目录

  • 项目核心内容
  • 实战目标
  • 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

课程链接

//appsqsyiqlk5791.h5.xiaoeknow.com/v1/course/video/v_5f39bdb8e4b01187873136cf?type=2

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: //www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

如有任何疑问,请与我联系 ([email protected]) 。