From abff541e3bf068df160ce2b594e47f5fce006a88 Mon Sep 17 00:00:00 2001 From: hello Date: Wed, 27 Mar 2024 14:46:57 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=94=E8=AE=B0=E6=9B=B4=E6=96=B0=E5=86=85?= =?UTF-8?q?=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/helloshop/access-control-list.md | 126 +++++++++++++++++++++++++ notes/helloshop/authorization.md | 87 +---------------- notes/helloshop/test.md | 53 ----------- 3 files changed, 127 insertions(+), 139 deletions(-) create mode 100644 notes/helloshop/access-control-list.md delete mode 100644 notes/helloshop/test.md diff --git a/notes/helloshop/access-control-list.md b/notes/helloshop/access-control-list.md new file mode 100644 index 0000000..46106ad --- /dev/null +++ b/notes/helloshop/access-control-list.md @@ -0,0 +1,126 @@ +# 实现权限访问控制列表 + +## 授权三要素 + +主体、资源、操作。 例如:用户(主体)对文件(资源)的读写(操作)。主体、资源、操作三者之间的关系称为授权关系,基于这种关系,我们可以将授权关系抽象为一个三元组(主体,资源,操作),这个三元组就是授权的基本单位。 + +## 基于角色的访问控制 + +基于角色的访问控制(Role-Based Access Control,简称 RBAC)是一种访问控制模型,通过角色来控制用户对资源的访问权限。角色是一组权限的集合,用户通过分配角色来获取相应的权限。基于角色的访问控制模型简单易用。还有其它的访问控制模型,如基于属性的访问控制(Attribute-Based Access Control,简称 ABAC)。 + +![role-based-access-control](https://oss.xcode.me/notes/helloshop/role-based-access-control.svg) + + +## 权限访问控制列表 + +权限访问控制列表(Access Control List,简称 ACL)是一种权限控制模型,用于控制用户对资源的访问权限。ACL 通过为每个资源定义一个访问控制列表,来控制用户对资源的操作权限。 + +## ACL 存储设计 + +```csharp +public class PermissionGranted +{ + public int Id { get; set; } + + public int RoleId { get; set; } + + public required string PermissionName { get; set; } + + public string? ResourceType { get; set; } + + public string? ResourceId { get; set; } +} +``` + +## 在 DbContext 中配置 ACL 实体 + +```csharp +public void Configure(EntityTypeBuilder builder) +{ + builder.ToTable("PermissionGranted"); + + builder.Property(x => x.Id); + builder.Property(x => x.PermissionName).HasMaxLength(64); + builder.Property(x => x.ResourceType).HasMaxLength(16); + builder.Property(x => x.ResourceId).HasMaxLength(32); + + builder.HasOne().WithMany().HasForeignKey(x => x.RoleId).IsRequired(); + + builder.HasIndex(x => new { x.RoleId, x.PermissionName, x.ResourceType, x.ResourceId }).IsUnique(); +} +``` + +## 权限 ACL 存储设计 + +```csharp +public class PermissionGranted +{ + public int Id { get; set; } + + public int RoleId { get; set; } + + public required string PermissionName { get; set; } + + public string? ResourceType { get; set; } + + public string? ResourceId { get; set; } +} +``` + +## 在 DbContext 中配置 ACL 实体 + +```csharp +public void Configure(EntityTypeBuilder builder) +{ + builder.ToTable("PermissionGranted"); + + builder.Property(x => x.Id); + builder.Property(x => x.PermissionName).HasMaxLength(64); + builder.Property(x => x.ResourceType).HasMaxLength(16); + builder.Property(x => x.ResourceId).HasMaxLength(32); + + builder.HasOne().WithMany().HasForeignKey(x => x.RoleId).IsRequired(); + + builder.HasIndex(x => new { x.RoleId, x.PermissionName, x.ResourceType, x.ResourceId }).IsUnique(); +} + +``` + +## 设计一个权限检查器 + +```csharp +public interface IPermissionChecker +{ + Task IsGrantedAsync(string name, string? resourceType = null, string? resourceId = null); + + Task IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name, string? resourceType = null, string? resourceId = null); +} +``` + +## 实现抽象的权限检查器 + +遍历每个角色的权限,如果有一个角色拥有该权限,则返回 true,表示授权通过。 + +```csharp + +public abstract class PermissionChecker : IPermissionChecker +{ + public abstract Task IsGrantedAsync(string name, string? resourceType = null, string? resourceId = null); + + public abstract Task IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name, string? resourceType = null, string? resourceId = null); +} + +``` + +## 实现权限检查器 + +ACL 列表存储在数据库中,可以通过 DbContext 实现本地权限检查器,也可以通过 HttpClient 实现远程权限检查器。 + + +![permission-checker](https://oss.xcode.me/notes/helloshop/permission-checker.svg) + +```csharp +public class RemotePermissionChecker: PermissionChecker + +public class LocalPermissionChecker: PermissionChecker +``` \ No newline at end of file diff --git a/notes/helloshop/authorization.md b/notes/helloshop/authorization.md index 2c937db..e831ccb 100644 --- a/notes/helloshop/authorization.md +++ b/notes/helloshop/authorization.md @@ -1,89 +1,4 @@ -# 基于策略和资源的授权系统 - -身份认证完成后 HttpContext.User 中包含了用户的身份信息,但是用户的身份信息并不包含用户的权限信息。用户的权限信息需要通过授权系统来获取。 - -## 授权三要素 - -授权系统的核心是授权三要素:授权主体、授权策略、资源。授权主体是指需要进行授权的对象,可以是用户,也可以是角色,也可以是组织机构。授权策略是指授权的规则,可以是基于角色的授权策略,也可以是基于资源的授权策略。资源是指需要授权的对象,可以是数据,也可以是服务。 - -例如:张三(授权主体)有订单001(资源)的查看权限(授权策略),管理员(授权主体)有所有订单(资源)的管理权限(授权策略)。 - -资源更细粒度的描述:资源类型、资源标识、资源属性。 - -例如:张三(授权主体)有订单001的金额和支付时间(资源)的查看权限(授权策略) - -值得一说的是组织结构,部门,第三方系统,等其它类型的主体,都可以与某个角色绑定,这样就可以实现对某个部门的权限控制。 - - -## 常见的权限控制模型 - -常见的权限控制模型有:DAC(Discretionary Access Control)、MAC(Mandatory Access Control)、RBAC(Role-Based Access Control)、ABAC(Attribute-Based Access Control)。 - -## 基于角色的访问控制 - -基于角色的访问控制是指通过角色来控制用户对资源的访问权限。角色是一组权限的集合,用户通过分配角色来获取相应的权限。基于角色的访问控制模型简单易用,但是角色的管理和权限的分配比较复杂。 - -## 权限 ACL 存储设计 - -```csharp -public class PermissionGranted -{ - public int Id { get; set; } - - public int RoleId { get; set; } - - public required string PermissionName { get; set; } - - public string? ResourceType { get; set; } - - public string? ResourceId { get; set; } -} -``` - -## 在 DbContext 中配置 ACL 实体 - -```csharp -public void Configure(EntityTypeBuilder builder) -{ - builder.ToTable("PermissionGranted"); - - builder.Property(x => x.Id); - builder.Property(x => x.PermissionName).HasMaxLength(64); - builder.Property(x => x.ResourceType).HasMaxLength(16); - builder.Property(x => x.ResourceId).HasMaxLength(32); - - builder.HasOne().WithMany().HasForeignKey(x => x.RoleId).IsRequired(); - - builder.HasIndex(x => new { x.RoleId, x.PermissionName, x.ResourceType, x.ResourceId }).IsUnique(); -} - -``` - -## 设计一个权限检查器 - -```csharp -public interface IPermissionChecker -{ - Task IsGrantedAsync(string name, string? resourceType = null, string? resourceId = null); - - Task IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name, string? resourceType = null, string? resourceId = null); -} -``` - -## 实现权限检查器 - - -![permission-checker](https://oss.xcode.me/notes/helloshop/permission-checker.svg) - -```csharp -public class RemotePermissionChecker: IPermissionChecker - -public class LocalPermissionChecker: IPermissionChecker -``` - -## 实现权限检查器 - -使用 DbContext 实现本地权限检查器,使用 HttpClient 实现远程权限检查器。 +# 基于策略和资源的授权机制 ## ASP.NET Core 中的授权系统 diff --git a/notes/helloshop/test.md b/notes/helloshop/test.md deleted file mode 100644 index 99a309c..0000000 --- a/notes/helloshop/test.md +++ /dev/null @@ -1,53 +0,0 @@ -# 程序员修炼之道 第二版 读书笔记 - -## 第 4 章 务实的偏执 - -无法写出完美的软件,但是我们可以写出更好的软件,我们需要不断地改进软件,不断地重构软件,不断地学习新的技术,不断地提高自己的技能。 - -### 死掉的程序不会说谎 - -一个程序死掉了,说明它有问题,我们需要找出问题所在,然后解决问题,不要忽略问题,不要让问题变得更糟,不要认为重启就是解决问题的办法。 - -### 尽早暴露问题 - -尽早暴露问题可以使得问题变得更容易解决,如果我们能够在编译时暴露问题,那么我们就可以在编译时解决问题,如果我们能够在测试时暴露问题,那么我们就可以在测试时解决问题,如果我们能够在运行时暴露问题,那么我们就可以在运行时解决问题。 - -### 断言式编程 - -断言式编程是一种防御式编程,它可以使得程序在运行时暴露问题,断言式编程可以使得程序变得更加健壮,但是断言式编程也会使得程序变得更加复杂,因为我们需要在程序中插入大量的断言语句,断言式编程可以使得程序变得更加难以理解和调试。 - - -## 第 5 章 宁弯不折 - -### 降低耦合度 - -依赖性是指一个模块在不改变自身的情况下,能够使用另一个模块的内部特性,为了更灵活,我们需要尽量减少依赖性,一些设计模式可以帮助我们解耦。 - -### 避免全局数据 - -全局数据是一种依赖性,它会使模块之间产生耦合,全局数据会使得模块之间的关系变得复杂,增加了理解和维护的难度,如果全局数据是可变的,那么它还会引入并发问题,可以封装全局数据,通过统一的函数来访问。 - -### 观察者模式 - -事件驱动是一种松耦合的设计,模块之间通过事件进行通信,模块不需要知道其他模块的存在,只需要关心自己的事件,事件驱动可以使得模块之间的关系变得简单,但是也会使得程序的执行流程变得复杂,因为事件的处理是异步的,事件驱动的程序会变得难以理解和调试。 - -### 管道和过滤器 - -管道和过滤器是一种流水线式的设计,每个过滤器都是一个独立的模块,它们之间通过管道连接,每个过滤器只需要关心自己的输入和输出,不需要关心其他过滤器的存在,这种设计可以使得模块之间的关系变得简单,但是也会使得程序的执行流程变得复杂,因为过滤器的处理是异步的,过滤器式的程序会变得难以理解和调试。 - - -## 第 6 章 并发 - -并发性指的是两个或更多个代码段在执行过程中表现得像是在同时运行一样,并行性是指它们的确是在同一时刻一起运行。 - -现代计算机的多核处理器使得并发编程变得更加重要,但是并发编程也会引入一些问题,比如竞态条件、死锁、饥饿、活锁等。 - -### 分析工作流提高并发性 - -工作流是一种并发编程的模型,它可以将一个大的任务分解成多个小的任务,然后并发执行这些小的任务,工作流可以提高程序的并发性。 - -### 减少共享数据 - -共享数据是一种依赖性,它会使模块之间产生耦合,共享数据会使得模块之间的关系变得复杂。 - -