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

2022-03-22 16:12:01 浏览数 (1)

学习分享 丨作者 /

这是DotNet NB 公众号的第186篇原创文章

目录

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

0 人点赞