广州站,东莞朝阳企讯通科技,网站视频怎么做的好处,网站建设与维护书籍推荐1简介ABP vNext框架本身提供了一套权限框架#xff0c;其功能非常丰富#xff0c;具体可参考官方文档#xff1a;https://docs.abp.io/en/abp/latest/Authorization但是我们使用时会发现#xff0c;对于正常的单体应用#xff0c;ABP vNext框架提供的权限系统没有问题其功能非常丰富具体可参考官方文档https://docs.abp.io/en/abp/latest/Authorization但是我们使用时会发现对于正常的单体应用ABP vNext框架提供的权限系统没有问题 但是在微服务架构下这种权限系统并不是非常的友好。我希望我的权限系统可以满足以下要求每个聚合服务持有独立的权限集合每个聚合服务可以独立声明、使用其接口访问所需的权限。提供统一接口负责管理、存储所有服务权限并实现对角色的授权。每个接口可以灵活组合使用一个或多个权限码。权限框架使用尽量简单减少额外编码量。在ABP vNext框架基础上重新编写了一套分布式权限框架大体规则如下使用ABP vNext框架中提供的用户、角色模型不做改变替代重新定义权限模型重新定义权限的实体及相关服务接口。在身份管理服务中实现权限的统一管理、角色授权和权限认证。在聚合服务中定义其具有的权限信息、权限关系并通过特性声明各接口所需要的权限。在聚合服务启动时自动将其权限信息注册到身份管理服务。客户端访问聚合服务层服务时在聚合服务层中间件中验证当前用户是否具有该接口权限验证过程需调用身份管理服务对应接口。 权限系统具体实现见下文。2身份认证服务在之前的文章中我们已经搭建了身份认证服务的基础框架这里我们直接在此基础上新增代码。在Demo.Identity.Domain项目中添加Permissions文件夹并添加Entities子文件夹。在此文件夹下添加实体类SysPermission和RolePermissions如下using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Domain.Entities;namespace Demo.Identity.Permissions.Entities;/// summary
/// 权限实体类
/// /summary
public class SysPermission : EntityGuid
{/// summary/// 服务名称/// /summary[MaxLength(64)]public string ServiceName { get; set; }/// summary/// 权限编码/// /summary[MaxLength(128)]public string Code { get; set; }/// summary/// 权限名称/// /summary[MaxLength(64)]public string Name { get; set; }/// summary/// 上级权限ID/// /summary[MaxLength(128)]public string ParentCode { get; set; }/// summary/// 判断两个权限是否相同/// /summary/// param nameobj/param/// returns/returnspublic override bool Equals(object? obj)
{return obj is SysPermission permission permission.ServiceName ServiceName permission.Name Name permission.Code Code permission.ParentCode ParentCode;}/// summary/// 设置ID的值/// /summary/// param nameid/parampublic void SetId(Guid id)
{Id id;}
}using System;
using Volo.Abp.Domain.Entities;namespace Demo.Identity.Permissions.Entities;/// summary
/// 角色权限对应关系
/// /summary
public class RolePermissions : EntityGuid
{/// summary/// 角色编号/// /summarypublic Guid RoleId { get; set; }/// summary/// 权限编号/// /summarypublic Guid PermissionId { get; set; }
}将Demo.Identity.Application.Contracts项目中原有Permissions文件夹中所有类删除并添加子文件夹Dto。在此文件夹下添加SysPermissionDto、PermissionTreeDto、SetRolePermissionsDto类如下using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Application.Dtos;namespace Demo.Identity.Permissions.Dto;/// summary
/// 权限DTO
/// /summary
public class SysPermissionDto:EntityDtoGuid
{/// summary/// 服务名称/// /summary[MaxLength(64)]public string ServiceName { get; set; }/// summary/// 权限编码/// /summary[MaxLength(128)]public string Code { get; set; }/// summary/// 权限名称/// /summary[MaxLength(64)]public string Name { get; set; }/// summary/// 上级权限ID/// /summary[MaxLength(128)]public string ParentCode { get; set; }
}using System;
using System.Collections.Generic;
using Volo.Abp.Application.Dtos;namespace Demo.Identity.Permissions.Dto;/// summary
/// 权限树DTO
/// /summary
public class PermissionTreeDto : EntityDtoGuid
{/// summary/// 服务名称/// /summarypublic string ServiceName { get; set; }/// summary/// 权限编码/// /summarypublic string Code { get; set; }/// summary/// 权限名称/// /summarypublic string Name { get; set; }/// summary/// 上级权限ID/// /summarypublic string ParentCode { get; set; }/// summary/// 子权限/// /summarypublic ListPermissionTreeDto Children { get; set; }}using System;
using System.Collections.Generic;namespace Demo.Identity.Permissions.Dto;/// summary
/// 设置角色权限DTO
/// /summary
public class SetRolePermissionsDto
{/// summary/// 角色编号/// /summarypublic Guid RoleId { get; set; }/// summary/// 权限ID列表/// /summarypublic ListGuid Permissions { get; set; }
}将Demo.Identity.Application.Contracts项目中Permissions文件夹下添加接口IRolePermissionsAppService如下using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Demo.Identity.Permissions.Dto;
using Volo.Abp.Application.Services;namespace Demo.Identity.Permissions;/// summary
/// 角色管理应用服务接口
/// /summary
public interface IRolePermissionsAppService: IApplicationService
{/// summary/// 获取角色所有权限/// /summary/// param nameroleId角色ID/param/// returns/returnsTaskListPermissionTreeDto GetPermission(Guid roleId);/// summary/// 设置角色权限/// /summary/// param namedto角色权限信息/param/// returns/returnsTask SetPermission(SetRolePermissionsDto dto);
}将Demo.Identity.Application.Contracts项目中Permissions文件夹下添加接口ISysPermissionAppService如下using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Demo.Identity.Permissions.Dto;
using Volo.Abp.Application.Services;namespace Demo.Identity.Permissions;/// summary
/// 权限管理应用服务接口
/// /summary
public interface ISysPermissionAppService:IApplicationService
{/// summary/// 按服务注册权限/// /summary/// param nameserviceName服务名称/param/// param namepermissions权限列表/param/// returns/returnsTaskbool RegistPermission(string serviceName, ListSysPermissionDto permissions);/// summary/// 按服务获取权限/// /summary/// param nameserviceName服务名称/param/// returns查询结果/returnsTaskListSysPermissionDto GetPermissions(string serviceName);/// summary/// 获取完整权限树/// /summary/// param namePermission/param/// returns查询结果/returnsTaskListPermissionTreeDto GetPermissionTree();/// summary/// 获取用户权限码/// /summary/// param nameuserId用户编号/param/// returns查询结果/returnsTaskListstring GetUserPermissionCode(Guid userId);
}在公共类库文件夹common中创建.Net6类库项目项目Demo.Core用于存放通用类。这里我们在Demo.Core中添加文件夹CommonExtension用于存放通用扩展添加EnumExtensions和ListExtensions类如下namespace Demo.Core.CommonExtension;/// summary
/// 枚举扩展类
/// /summary
public static class EnumExtensions
{/// summary/// 获取描述特性/// /summary/// param nameenumValue枚举值/param/// returns/returnspublic static string GetDescription(this Enum enumValue){string value enumValue.ToString();FieldInfo field enumValue.GetType().GetField(value);object[] objs field.GetCustomAttributes(typeof(DescriptionAttribute), false); //获取描述属性if (objs null || objs.Length 0) //当描述属性没有时直接返回名称return value;DescriptionAttribute descriptionAttribute (DescriptionAttribute)objs[0];return descriptionAttribute.Description;}
}namespace Demo.Core.CommonExtension;public static class ListExtensions
{/// summary/// 集合去重/// /summary/// param namelst目标集合/param/// param namekeySelector去重关键字/param/// typeparam nameT集合元素类型/typeparam/// typeparam nameTKey去重关键字数据类型/typeparam/// returns去重结果/returnspublic static ListT DistinctT,TKey(this ListT lst,FuncT, TKey keySelector){ListT result new ListT();HashSetTKey set new HashSetTKey();foreach (var item in lst){var key keySelector(item);if (!set.Contains(key)){set.Add(key);result.Add(item);}}return result;}
}在Demo.Core项目中添加文件夹CommonFunction用于存放通用方法这里我们添加用于集合比对的ListCompare类如下using VI.Core.CommonExtension;namespace VI.Core.CommonFunction;/// summary
/// 集合比对
/// /summary
public class ListCompare
{/** 调用实例* MutiComparePermission, string(lst1, lst2, x x.Code, (obj, isnew) * {* if (isnew)* {* Console.WriteLine($新增项{obj.Id});* }* else* {* Console.WriteLine($已存在{obj.Id});* }* }, out var lstNeedRemove);*//// summary/// 对比源集合和目标集合处理已有项和新增项并找出需要删除的项/// /summary/// param namelstSource源集合/param/// param namelstDestination目标集合/param/// param namekeySelector集合比对关键字/param/// param nameaction新增或已有项处理方法参数数据项, 是否是新增/param/// param nameneedRemove需要删除的数据集/param/// typeparam nameTObject集合对象数据类型/typeparam/// typeparam nameTKey对比关键字数据类型/typeparampublic static void MutiCompareTObject,TKey(ListTObject lstDestination,ListTObject lstSource,FuncTObject, TKey keySelector,ActionTObject, bool action, out DictionaryTKey, TObject needRemove){//目标集合去重lstDestination.Distinct(keySelector);//将源集合存入字典提高查询效率needRemove new DictionaryTKey, TObject();foreach (var item in lstSource){needRemove.Add(keySelector(item),item);}//遍历目标集合区分新增项及已有项//在字典中排除目标集合中的项剩余的即为源集合中需删除的项foreach (var item in lstDestination){if (needRemove.ContainsKey(keySelector(item))){action(item, false);needRemove.Remove(keySelector(item));}else{action(item, true);}}}
}在Demo.Identity.Application项目中添加Permissions文件夹。在Demo.Identity.Application项目Permissions文件夹中添加PermissionProfileExtensions类用于定义对象映射关系如下using Demo.Identity.Permissions.Dto;
using Demo.Identity.Permissions.Entities;namespace Demo.Identity.Permissions;public static class PermissionProfileExtensions
{/// summary/// 创建权限领域相关实体映射关系/// /summary/// param nameprofile/parampublic static void CreatePermissionsMap(this IdentityApplicationAutoMapperProfile profile){profile.CreateMapSysPermission, PermissionTreeDto();profile.CreateMapSysPermission,SysPermissionDto();profile.CreateMapSysPermissionDto,SysPermission();}
}在Demo.Identity.Application项目IdentityApplicationAutoMapperProfile类的IdentityApplicationAutoMapperProfile方法中添加如下代码this.CreatePermissionsMap();在Demo.Identity.Application项目Permissions文件夹中添加PermissionTreeBuilder类定义构造权限树形结构的通用方法如下using System.Collections.Generic;
using System.Linq;
using Demo.Identity.Permissions.Dto;namespace Demo.Identity.Permissions;/// summary
/// 权限建树帮助类
/// /summary
public static class PermissionTreeBuilder
{/// summary/// 建立树形结构/// /summary/// param namelst/param/// returns/returnspublic static ListPermissionTreeDto Build(ListPermissionTreeDto lst){var result lst.ToList();for (var i 0; i result.Count; i){if (result[i].ParentCode null){continue;}foreach (var item in lst){item.Children ?? new ListPermissionTreeDto();if (item.Code ! result[i].ParentCode){continue;}item.Children.Add(result[i]);result.RemoveAt(i);i--;break;}}return result;}
}之后我们在Demo.Identity.Application项目Permissions文件夹中添加权限管理实现类SysPermissionAppService如下using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Demo.Core.CommonFunction;
using Demo.Identity.Permissions.Dto;
using Demo.Identity.Permissions.Entities;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using Demo.Core.CommonExtension;namespace Demo.Identity.Permissions
{/// summary/// 权限管理应用服务/// /summarypublic class SysPermissionAppService : IdentityAppService, ISysPermissionAppService{#region 初始化private readonly IRepositoryRolePermissions _rolePermissionsRepository;private readonly IRepositorySysPermission _sysPermissionsRepository;private readonly IRepositoryIdentityUserRole _userRolesRepository;public SysPermissionAppService(IRepositoryRolePermissions rolePermissionsRepository,IRepositorySysPermission sysPermissionsRepository,IRepositoryIdentityUserRole userRolesRepository
){_rolePermissionsRepository rolePermissionsRepository;_sysPermissionsRepository sysPermissionsRepository;_userRolesRepository userRolesRepository;}#endregion#region 按服务注册权限/// summary/// 按服务注册权限/// /summary/// param nameserviceName服务名称/param/// param namepermissions权限列表/param/// returns/returnspublic async Taskbool RegistPermission(string serviceName, ListSysPermissionDto permissions){//根据服务名称查询现有权限var entities await AsyncExecuter.ToListAsync( (await _sysPermissionsRepository.GetQueryableAsync()).Where(c c.ServiceName serviceName));var lst ObjectMapper.MapListSysPermissionDto, ListSysPermission(permissions);ListCompare.MutiCompare(lst, entities, x x.Code, async (entity, isNew) {if (isNew){//新增await _sysPermissionsRepository.InsertAsync(entity);}else{//修改var tmp lst.FirstOrDefault(x x.Code entity.Code);//调用权限判断方法,如果code和name相同就不进行添加if (!entity.Equals(tmp)tmp!null){entity.SetId(tmp.Id);await _sysPermissionsRepository.UpdateAsync(entity);}}}, out var needRemove);foreach (var item in needRemove){//删除多余项await _sysPermissionsRepository.DeleteAsync(item.Value);}return true;}#endregion#region 按服务获取权限/// summary/// 按服务获取权限/// /summary/// param nameserviceName服务名称/param/// returns查询结果/returnspublic async TaskListSysPermissionDto GetPermissions(string serviceName){var query (await _sysPermissionsRepository.GetQueryableAsync()).Where(x x.ServiceName serviceName);//使用AsyncExecuter进行异步查询var lst await AsyncExecuter.ToListAsync(query);//映射实体类到dtoreturn ObjectMapper.MapListSysPermission, ListSysPermissionDto(lst);}#endregion#region 获取完整权限树/// summary/// 获取完整权限树/// /summary/// returns查询结果/returnspublic async TaskListPermissionTreeDto GetPermissionTree(){var per await _sysPermissionsRepository.ToListAsync();var lst ObjectMapper.MapListSysPermission, ListPermissionTreeDto(per);return PermissionTreeBuilder.Build(lst);}#endregion#region 获取用户权限码/// summary/// 获取用户权限码/// /summary/// param nameuserId用户编号/param/// returns查询结果/returnspublic async TaskListstring GetUserPermissionCode(Guid userId){var query from user in (await _userRolesRepository.GetQueryableAsync()).Where(c c.UserId userId)join rp in (await _rolePermissionsRepository.GetQueryableAsync()) on user.RoleId equals rp.RoleIdjoin pe in (await _sysPermissionsRepository.GetQueryableAsync()) on rp.PermissionId equals pe.Idselect pe.Code;var permission await AsyncExecuter.ToListAsync(query);return permission.Distinct(xx);}#endregion}
}添加角色权限关系管理实现类RolePermissionsAppService如下using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Demo.Identity.Permissions.Dto;
using Demo.Identity.Permissions.Entities;
using Volo.Abp.Domain.Repositories;namespace Demo.Identity.Permissions
{/// summary/// 角色管理应用服务/// /summarypublic class RolePermissionsAppService : IdentityAppService, IRolePermissionsAppService{#region 初始化private readonly IRepositoryRolePermissions _rolePermissionsRepository;private readonly IRepositorySysPermission _sysPermissionsRepository;public RolePermissionsAppService(IRepositoryRolePermissions rolePermissionsRepository,IRepositorySysPermission sysPermissionsRepository
){_rolePermissionsRepository rolePermissionsRepository;_sysPermissionsRepository sysPermissionsRepository;}#endregion#region 获取角色所有权限/// summary/// 获取角色所有权限/// /summary/// param nameroleId角色ID/param/// returns/returnspublic async TaskListPermissionTreeDto GetPermission(Guid roleId){var query from rp in (await _rolePermissionsRepository.GetQueryableAsync()).Where(x x.RoleId roleId)join permission in (await _sysPermissionsRepository.GetQueryableAsync())on rp.PermissionId equals permission.Idselect permission;var permissions await AsyncExecuter.ToListAsync(query);var lst ObjectMapper.MapListSysPermission, ListPermissionTreeDto(permissions);return PermissionTreeBuilder.Build(lst);}#endregion#region 设置角色权限/// summary/// 设置角色权限/// /summary/// param nameroleId橘色编号/param/// param namepermissions权限编号/param/// returns/returnspublic async Task SetPermission(SetRolePermissionsDto dto){await _rolePermissionsRepository.DeleteAsync(x x.RoleId dto.RoleId);foreach (var permissionId in dto.Permissions){RolePermissions entity new RolePermissions(){PermissionId permissionId,RoleId dto.RoleId,};await _rolePermissionsRepository.InsertAsync(entity);}}#endregion}
} 在Demo.Identity.EntityFrameworkCore项目IdentityDbContext类中加入以下属性public DbSetSysPermission SysPermissions { get; set; }
public DbSetRolePermissions RolePermissions { get; set; }在Demo.Identity.EntityFrameworkCore项目目录下启动命令提示符执行以下命令分别创建和执行数据迁移dotnet-ef migrations add AddPermissions
dotnet-ef database update在Demo.Identity.EntityFrameworkCore项目IdentityEntityFrameworkCoreModule类ConfigureServices方法中找到 options.AddDefaultRepositories(includeAllEntities: true); 在其后面加入以下代码options.AddDefaultRepositoryIdentityUserRole();完成后运行身份管理服务可正常运行和访问各接口则基础服务层修改完成。后续操作请看下一篇end更多精彩关注我获得