
添加一个 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; } }}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) 。