.NET 云原生架构师训练营(权限系统 代码实现 Identity)--学习笔记
目录
- 开发任务
- 代码实现
开发任务
- DotNetNB.Security.Core:定义 core,models,Istore;实现 default memory store
- DotNetNB.Security.Identity:将权限赋予角色或用户;在用户登录时将 Permissions 写入用户身份 claims

代码实现
添加一个 Identity 的扩展,将 role 和 Permission 结合到一起
定义 IRolePermissionManager 接口,提供一个 AddRolePermission 的方法
using DotNetNB.Security.Core.Models;
namespace DotNetNB.Security.Identity
{
public interface IRolePermissionManager<TRole>
{
public Task AddRolePermission(TRole role, Permission permission);
}
}
新增 RolePermissionManager 继承 IRolePermissionManager,将 resource 的 key 存到 role 的 Claim 中
因为这样只在 role 里面记录了 key,不知道来自哪个 permission,所以还需要持久化 permission 和 role 的关系
using DotNetNB.Security.Core;
using DotNetNB.Security.Core.Models;
using Microsoft.AspNetCore.Identity;
using System.Security.Claims;
namespace DotNetNB.Security.Identity
{
public class RolePermissionManager<TRole> : IRolePermissionManager<TRole> where TRole : class
{
private readonly RoleManager<TRole> _roleManager;
public RolePermissionManager(RoleManager<TRole> roleManager)
{
_roleManager = roleManager;
}
public async Task AddRolePermission(TRole role, Permission permission)
{
foreach (var resource in permission.Resources)
{
await _roleManager.AddClaimAsync(role, new Claim(ClaimsTypes.Permission, resource.Key));
}
//TBD 持久化 permission 和 role 的关系
}
}
}
由于无法直接获取到 Permission,只能获取到 Permission 的 key,所以需要在 IPermissionManager 接口中添加一个 GetAsync 方法
public Task<Permission> GetAsync(string key);
在 PermissionManager 中实现 GetAsync 方法
public async Task<Permission> GetAsync(string key)
{
return await _permissionStore.GetByKeyAsync(key);
}
这样在 RolePermissionManager 中就可以通过这个方法获取到 Permission
using DotNetNB.Security.Core;
using Microsoft.AspNetCore.Identity;
using System.Security.Claims;
namespace DotNetNB.Security.Identity
{
public class RolePermissionManager<TRole> : IRolePermissionManager<TRole> where TRole : class
{
private readonly IPermissionManager _permissionManager;
private readonly RoleManager<TRole> _roleManager;
public RolePermissionManager(IPermissionManager permissionManager, RoleManager<TRole> roleManager)
{
_permissionManager = permissionManager;
_roleManager = roleManager;
}
public async Task AddRolePermission(TRole role, string permissionKey)
{
var permission = await _permissionManager.GetAsync(permissionKey);
if (permission == null)
{
throw new InvalidOperationException($"Permission not found:{permissionKey}");
}
foreach (var resource in permission.Resources)
{
await _roleManager.AddClaimAsync(role, new Claim(ClaimsTypes.Permission, resource.Key));
}
//TBD 持久化 permission 和 role 的关系
}
}
}
实际上用户可能也获取不到 TRole,需要通过 roleId 查询
public async Task AddRolePermission(string roleId, string permissionKey)
{
var role = await _roleManager.FindByIdAsync(roleId);
if (role == null)
{
throw new InvalidOperationException($"Role not found:{roleId}");
}
var permission = await _permissionManager.GetAsync(permissionKey);
if (permission == null)
{
throw new InvalidOperationException($"Permission not found:{permissionKey}");
}
foreach (var resource in permission.Resources)
{
await _roleManager.AddClaimAsync(role, new Claim(ClaimsTypes.Permission, resource.Key));
}
//TBD 持久化 permission 和 role 的关系
}
用户也是一样的做法,定义一个 IUserPermissionManager 接口,提供一个 AddUserPermission 方法
namespace DotNetNB.Security.Identity
{
public interface IUserPermissionManager<TUser>
{
public Task AddUserPermission(string userId, string permissionKey);
}
}
新增 UserPermissionManager 继承 IUserPermissionManager,将 Permission 中所有 Resource 的 key 作为 User 的 Claim
using System.Security.Claims;
using DotNetNB.Security.Core;
using Microsoft.AspNetCore.Identity;
namespace DotNetNB.Security.Identity
{
public class UserPermissionManager<TUser> : IUserPermissionManager<TUser> where TUser : class
{
private readonly UserManager<TUser> _userManager;
private readonly IPermissionManager _permissionManager;
public UserPermissionManager(UserManager<TUser> userManager, IPermissionManager permissionManager)
{
_userManager = userManager;
_permissionManager = permissionManager;
}
public async Task AddUserPermission(string userId, string permissionKey)
{
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
throw new InvalidOperationException($"User not found:{userId}");
}
var permission = await _permissionManager.GetAsync(permissionKey);
if (permission == null)
{
throw new InvalidOperationException($"Permission not found:{permissionKey}");
}
var claims = permission.Resources.Select(p => new Claim(ClaimsTypes.Permission, p.Key)).ToList();
await _userManager.AddClaimsAsync(user, claims);
}
}
}
提供一个扩展方法将 RolePermissionManager 和 UserPermissionManager 添加到程序中
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
namespace DotNetNB.Security.Identity.Extensions
{
public static class IdentityBuilderExtensions
{
public static IdentityBuilder WithPermissions<TUser, TRole>(this IdentityBuilder identityBuilder)
where TRole : class where TUser : class
{
identityBuilder.Services.AddScoped<IRolePermissionManager<TRole>, RolePermissionManager<TRole>>()
.AddScoped<IUserPermissionManager<TUser>, UserPermissionManager<TUser>>();
return identityBuilder;
}
}
}
GitHub源码链接:
https://github.com/MingsonZheng/dotnetnb.security
课程链接
https://appsqsyiqlk5791.h5.xiaoeknow.com/v1/course/video/v_5f39bdb8e4b01187873136cf?type=2

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。
.NET 云原生架构师训练营(权限系统 代码实现 Identity)--学习笔记的更多相关文章
- .NET 云原生架构师训练营(建立系统观)--学习笔记
目录 目标 ASP .NET Core 什么是系统 什么是系统思维 系统分解 什么是复杂系统 作业 目标 通过整体定义去认识系统 通过分解去简化对系统的认识 ASP .NET Core ASP .NE ...
- .NET 云原生架构师训练营(对象过程建模)--学习笔记
目录 UML OPM OPM优化 UML 1997年发布UML标准 主要域 视图 图 主要概念 结构 静态视图 类图 类.关联.泛化.依赖关系.实现.接口 用例视图 用例图 用例.参与者.关联.扩展. ...
- .NET 云原生架构师训练营(设计原则&&设计模式)--学习笔记
目录 设计原则 设计模式 设计原则 DRY (Don't repeat yourself 不要重复) KISS (Keep it stupid simple 简单到傻子都能看懂) YAGNI (You ...
- .NET 云原生架构师训练营(责任链模式)--学习笔记
目录 责任链模式 源码 责任链模式 职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无需关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了 何时使用:在处理 ...
- .NET 云原生架构师训练营(系统架构)--学习笔记
目录 对外展现的功能 内部功能 功能交互与价值通路 系统架构 目标 认识系统的价值通路 认识功能架构,通过把功能结构与形式结构结合来描述系统架构 受益原则 好的架构必须使人受益,要想把架构做好,就要专 ...
- .NET 云原生架构师训练营(模块一 架构师与云原生)--学习笔记
目录 什么是软件架构 软件架构的基本思路 单体向分布式演进.云原生.技术中台 1.1 什么是软件架构 1.1.1 什么是架构? Software architecture = {Elements, F ...
- .NET 云原生架构师训练营(权限系统 RGCA 架构设计)--学习笔记
目录 项目核心内容 实战目标 RGCA 四步架构法 项目核心内容 无代码埋点实现对所有 API Action 访问控制管理 对 EF Core 实体新增.删除.字段级读写控制管理 与 Identity ...
- .NET 云原生架构师训练营(权限系统 RGCA 开发任务)--学习笔记
目录 目标 模块拆分 OPM 开发任务 目标 基于上一讲的模块划分做一个任务拆解,根据任务拆解实现功能 模块拆分 模块划分已经完成了边界的划分,边界内外职责清晰 OPM 根据模块拆分画出 OPM(Ob ...
- .NET 云原生架构师训练营(权限系统 代码实现 ActionAccess)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.Secu ...
随机推荐
- 使用VUE组件创建SpreadJS自定义单元格(二)
在上篇中,我们介绍了如何通过设置runtimeCompiler为true,在Vue中实现了动态创建电子表格组件.想了解具体内容可看点击查看使用VUE组件创建SpreadJS自定义单元格(一). 但是在 ...
- WebRTC本地选择codec(web本地模拟)
视频编码后,再进行发送.WebRTC建立视频连接前,可以选择codec.一般来说支持多种codec,以VP8和H264为代表. Codec: 编码译码器,编解码器 示例代码 写一个示例,用户可以在发送 ...
- 刨根问底: Kafka 到底会不会丢数据?
大家好,我是 华仔, 又跟大家见面了. 上一篇作为专题系列的第二篇,从演进的角度带你深度剖析了关于 Kafka 请求处理全流程以及超高并发的网络架构设计的实现细节,今天开启第三篇,我们来聊聊 Kafk ...
- DbHelper 标准类
import java.io.*; import java.sql.*; import java.util.*; import javax.servlet.jsp.jstl.sql.*; public ...
- elasticsearch源码分析及插件开发
ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作为Apach ...
- 羽夏看Win系统内核——进程线程篇
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...
- js整体
1.引入 <script type="text/javascript"> 2.输出 使用 window.alert() 写入警告框 使用 document.write ...
- 集合框架-Map集合-TreeMap存储自定义对象
1 package cn.itcast.p8.treemap.demo; 2 3 4 import java.util.Iterator; 5 import java.util.Map; 6 impo ...
- 机器学习-softmax回归 python实现
---恢复内容开始--- Softmax Regression 可以看做是 LR 算法在多分类上的推广,即类标签 y 的取值大于或者等于 2. 假设数据样本集为:$\left \{ \left ( X ...
- (2)RabbitMQ架构设计与应用场景
1.什么是消息中间件? 消息是指应用间传输的数据.消息体包括文本字符串.Json.内嵌对象等.消息中间件是基于队列模型实现异步和同步传输数据的.作用:解耦,冗余(存储).扩展性.削峰.可恢复性.顺序保 ...