目录

  • 开发任务
  • 代码实现

开发任务

  • 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)--学习笔记的更多相关文章

  1. .NET 云原生架构师训练营(建立系统观)--学习笔记

    目录 目标 ASP .NET Core 什么是系统 什么是系统思维 系统分解 什么是复杂系统 作业 目标 通过整体定义去认识系统 通过分解去简化对系统的认识 ASP .NET Core ASP .NE ...

  2. .NET 云原生架构师训练营(对象过程建模)--学习笔记

    目录 UML OPM OPM优化 UML 1997年发布UML标准 主要域 视图 图 主要概念 结构 静态视图 类图 类.关联.泛化.依赖关系.实现.接口 用例视图 用例图 用例.参与者.关联.扩展. ...

  3. .NET 云原生架构师训练营(设计原则&&设计模式)--学习笔记

    目录 设计原则 设计模式 设计原则 DRY (Don't repeat yourself 不要重复) KISS (Keep it stupid simple 简单到傻子都能看懂) YAGNI (You ...

  4. .NET 云原生架构师训练营(责任链模式)--学习笔记

    目录 责任链模式 源码 责任链模式 职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无需关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了 何时使用:在处理 ...

  5. .NET 云原生架构师训练营(系统架构)--学习笔记

    目录 对外展现的功能 内部功能 功能交互与价值通路 系统架构 目标 认识系统的价值通路 认识功能架构,通过把功能结构与形式结构结合来描述系统架构 受益原则 好的架构必须使人受益,要想把架构做好,就要专 ...

  6. .NET 云原生架构师训练营(模块一 架构师与云原生)--学习笔记

    目录 什么是软件架构 软件架构的基本思路 单体向分布式演进.云原生.技术中台 1.1 什么是软件架构 1.1.1 什么是架构? Software architecture = {Elements, F ...

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

    目录 项目核心内容 实战目标 RGCA 四步架构法 项目核心内容 无代码埋点实现对所有 API Action 访问控制管理 对 EF Core 实体新增.删除.字段级读写控制管理 与 Identity ...

  8. .NET 云原生架构师训练营(权限系统 RGCA 开发任务)--学习笔记

    目录 目标 模块拆分 OPM 开发任务 目标 基于上一讲的模块划分做一个任务拆解,根据任务拆解实现功能 模块拆分 模块划分已经完成了边界的划分,边界内外职责清晰 OPM 根据模块拆分画出 OPM(Ob ...

  9. .NET 云原生架构师训练营(权限系统 代码实现 ActionAccess)--学习笔记

    目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.Secu ...

随机推荐

  1. 使用 淘宝 接口,根据公网ip 获取地理信息

    1.  源码,点击查看 1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStr ...

  2. react中异步组件以及withRouter的使用

    什么是异步组件?简单来说就是异步加载一个组件,正常情况浏览器加载的是我们打包好的bundle.js文件,那么这个文件是集合了所有js是代码,然而我们首屏加载并不需要一次性加载所有的组件,这会造成性能的 ...

  3. 服务限流 -- 自定义注解基于RateLimiter实现接口限流

    1. 令牌桶限流算法 令牌桶会以一个恒定的速率向固定容量大小桶中放入令牌,当有浏览来时取走一个或者多个令牌,当发生高并发情况下拿到令牌的执行业务逻辑,没有获取到令牌的就会丢弃获取服务降级处理,提示一个 ...

  4. X-Forwarded-for漏洞解析

    首先了解X-Forwarded-for(简称:XFF) X-Forwarded-for:简称XFF,它代表客户端,也就是HTTP的请求真实的IP,只有在通过了HTTP代理或者负载均衡器时才会添加该项. ...

  5. golang中为何在同一个goroutine中使用无缓冲通道会导致死锁

    package main import "fmt" func main() { /* 以下程序会导致死锁 c := make(chan int) c <- 10 n1 := ...

  6. python使用pip安装库超时报错解决办法

    原因:pip源超时了,安装不上 pip install matplotlib -i http://pypi.douban.com/simple --trusted-host pypi.douban.c ...

  7. Homework_1

    寒假第一份作业 一.博客园部分 1.个人博客园链接 Click here 2.markdown界面截图 我用typora编辑 所以贴上typora界面的截图 二.Github部分 1.个人Github ...

  8. Visualizing and Understanding Convolutional Networks论文复现笔记

    目录 Visualizing and Understanding Convolutional Networks 论文复现笔记 Abstract Introduction Approach Visual ...

  9. WebAssembly环境搭建

    Environment:Ubuntu 16.06 + emscripten URL: https://emscripten.org/docs/getting_started/downloads.htm ...

  10. C++函数调用过程解析

    编译环境:Windows 10 + VS2015. 0.引言 函数调用的过程实际上也就是一个中断的过程,本文演示和深入分析参数入栈.函数跳转.保护现场.恢复现场等函数调用过程. 首先对三个常用的寄存器 ...