本文介绍了 RGCA 四步架构法的思路,通过 RGCA 四步架构法设计一个无代码埋点通用权限管理系统。
RGCA 四步架构法
好的架构必须使人受益,要想把架构做好,就要专注于功能的涌现,使得系统把它的主要功能通过跨越系统边界的接口对外展示出来
对于企业内部的管理系统而言基本上都会有一个权限管理系统,产品经理在进行产品设计的时候需要先确定每一个菜单,每一个按钮的 key 是什么,再将 key 与权限进行匹配、绑定
但是产品经理无法确定未来所有需要权限管理的地方,所以需要开发人员提前为所有地方设置 key
由于需要设置的 key 有很多,所以可能命名不规范,也有可能会有缺漏,未来涉及到遗漏的地方就需要开发人员重新编码、发布才能满足需求,这是开发企业内部权限管理功能的痛点▌利益相关者
受益人 | 需求 |
开发者 | 1、集成简单,少写代码; |
产品经理 | 1、随时可以增加对系统里面功能和数据的权限控制 |
系统管理员 | 1、希望能灵活对系统的权限进行配置,适合角色与员工结构,依照通用行业标准进行配置 |
开发者所属公司 | 1、低成本(划算); |
投资人 | 1、通过该项目的完整演示 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,不能覆盖原有的功能
保护资源的上一层是安全,安全除了保护资源,还有很多其他的事情可以做,比如记录日志审计日志会记录用户的所有访问记录,企业可以设置权限通过这种方式可以不停地将需求往上一层寻找,一直达到最顶层除了向上之外还可以向下寻找,延伸出整体概念,通过概念片段的组合,构成完整的整体概念接下来对拦截这一过程进行展开,展开为一组必须得到执行的内部过程,针对每一个内部过程,选用特定的操作数、过程及工具对象对其进行特化,就可以得到相应的概念片段,这也是一个特化的过程
从资源变成权限,权限绑定给用户,用户进行登录,登录之后再进行授权
资源分为 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 的权限
大体上分为以下几部分:
对每一层进行拆分,将功能拆分为 Core,Models,Store 和 EFStore
通过 RGCA 四步架构法从利益相关者获取需求,并将需求转化为目标(功能意图),接着将目标扩展为完整概念,最后将概念扩展为架构。按照 RGCA 四步架构法的思路,我们完成了对一个无代码埋点通用权限管理系统的设计,根据架构设计进行代码实现,具体实现可以参考项目完整代码,也可以参考该系列相关文章。
微软最有价值专家是微软公司授予第三方技术专业人士的一个全球奖项。29年来,世界各地的技术社区领导者,因其在线上和线下的技术社区中分享专业知识和经验而获得此奖项。MVP是经过严格挑选的专家团队,他们代表着技术最精湛且最具智慧的人,是对社区投入极大的热情并乐于助人的专家。MVP致力于通过演讲、论坛问答、创建网站、撰写博客、分享视频、开源项目、组织会议等方式来帮助他人,并最大程度地帮助微软技术社区用户使用 Microsoft 技术。更多详情请登录官方网站:
https://mvp.microsoft.com/zh-cn
点击链接继续发现更多有趣的微软第一方开发者节目!