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

博客 动态
0 346
羽尘
羽尘 2022-02-19 00:55:31
悬赏:0 积分 收藏

.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) 。

posted @ 2022-02-18 23:17 MingsonZheng 阅读(1) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员