.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 ...
随机推荐
- 使用 淘宝 接口,根据公网ip 获取地理信息
1. 源码,点击查看 1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStr ...
- react中异步组件以及withRouter的使用
什么是异步组件?简单来说就是异步加载一个组件,正常情况浏览器加载的是我们打包好的bundle.js文件,那么这个文件是集合了所有js是代码,然而我们首屏加载并不需要一次性加载所有的组件,这会造成性能的 ...
- 服务限流 -- 自定义注解基于RateLimiter实现接口限流
1. 令牌桶限流算法 令牌桶会以一个恒定的速率向固定容量大小桶中放入令牌,当有浏览来时取走一个或者多个令牌,当发生高并发情况下拿到令牌的执行业务逻辑,没有获取到令牌的就会丢弃获取服务降级处理,提示一个 ...
- X-Forwarded-for漏洞解析
首先了解X-Forwarded-for(简称:XFF) X-Forwarded-for:简称XFF,它代表客户端,也就是HTTP的请求真实的IP,只有在通过了HTTP代理或者负载均衡器时才会添加该项. ...
- golang中为何在同一个goroutine中使用无缓冲通道会导致死锁
package main import "fmt" func main() { /* 以下程序会导致死锁 c := make(chan int) c <- 10 n1 := ...
- python使用pip安装库超时报错解决办法
原因:pip源超时了,安装不上 pip install matplotlib -i http://pypi.douban.com/simple --trusted-host pypi.douban.c ...
- Homework_1
寒假第一份作业 一.博客园部分 1.个人博客园链接 Click here 2.markdown界面截图 我用typora编辑 所以贴上typora界面的截图 二.Github部分 1.个人Github ...
- Visualizing and Understanding Convolutional Networks论文复现笔记
目录 Visualizing and Understanding Convolutional Networks 论文复现笔记 Abstract Introduction Approach Visual ...
- WebAssembly环境搭建
Environment:Ubuntu 16.06 + emscripten URL: https://emscripten.org/docs/getting_started/downloads.htm ...
- C++函数调用过程解析
编译环境:Windows 10 + VS2015. 0.引言 函数调用的过程实际上也就是一个中断的过程,本文演示和深入分析参数入栈.函数跳转.保护现场.恢复现场等函数调用过程. 首先对三个常用的寄存器 ...