经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 其他 » 网络安全 » 查看文章
造轮子之权限管理
来源:cnblogs  作者:饭勺oO  时间:2023/10/11 16:12:22  对本文有异议

上文已经完成了自定义授权策略,那么接下来就得完善我们的权限管理了。不然没有数据,如何鉴权~

表设计

创建我们的表实体类:

  1. namespace Wheel.Domain.Permissions
  2. {
  3. public class PermissionGrant : Entity<Guid>
  4. {
  5. public string Permission { get; set; }
  6. public string GrantType { get; set; }
  7. public string GrantValue { get; set; }
  8. }
  9. }

Permission表示权限名称,结构为"{controllerName}:{actionName}"。
GrantType表示权限类型,如角色权限则R表示,方便后续在新增别的权限类型时可以灵活扩展。
GrantValue则表示权限类型对应的值,比如GrantType是R时,GrantValue是admin则表示admin角色的授权。

修改DbContext

在WheelDbContext添加代码:

  1. #region Permission
  2. public DbSet<PermissionGrant> PermissionGrants { get; set; }
  3. #endregion
  1. void ConfigurePermissionGrants(ModelBuilder builder)
  2. {
  3. builder.Entity<PermissionGrant>(b =>
  4. {
  5. b.HasKey(o => o.Id);
  6. b.Property(o => o.Permission).HasMaxLength(128);
  7. b.Property(o => o.GrantValue).HasMaxLength(128);
  8. b.Property(o => o.GrantType).HasMaxLength(32);
  9. });
  10. }

在OnModelCreating添加ConfigurePermissionGrants方法。

  1. protected override void OnModelCreating(ModelBuilder builder)
  2. {
  3. base.OnModelCreating(builder);
  4. ConfigurePermissionGrants(builder);
  5. }

接下来执行数据库迁移命令即可完成表创建。

实现权限管理

接下来就是实现我们的权限管理功能。
我们的PermissionManageAppService只需定义三个API即可满足管理需求。分别是获取当前用户所有权限,修改用户权限,获取指定角色权限。

  1. namespace Wheel.Services.PermissionManage
  2. {
  3. public interface IPermissionManageAppService : ITransientDependency
  4. {
  5. Task<R<List<GetAllPermissionDto>>> GetPermission();
  6. Task<R> UpdatePermission(UpdatePermissionDto dto);
  7. Task<R<List<GetAllPermissionDto>>> GetRolePermission(string RoleName);
  8. }
  9. }

具体实现代码如下:

  1. namespace Wheel.Services.PermissionManage
  2. {
  3. public class PermissionManageAppService : WheelServiceBase, IPermissionManageAppService
  4. {
  5. private readonly IBasicRepository<PermissionGrant, Guid> _permissionGrantRepository;
  6. private readonly RoleManager<Role> _roleManager;
  7. private readonly XmlCommentHelper _xmlCommentHelper;
  8. public PermissionManageAppService(XmlCommentHelper xmlCommentHelper, IBasicRepository<PermissionGrant, Guid> permissionGrantRepository, RoleManager<Role> roleManager)
  9. {
  10. _xmlCommentHelper = xmlCommentHelper;
  11. _permissionGrantRepository = permissionGrantRepository;
  12. _roleManager = roleManager;
  13. }
  14. public async Task<R<List<GetAllPermissionDto>>> GetPermission()
  15. {
  16. var result = await GetAllDefinePermission();
  17. if (CurrentUser.IsInRoles("admin"))
  18. {
  19. result.ForEach(p => p.Permissions.ForEach(a => a.IsGranted = true));
  20. }
  21. else
  22. {
  23. var grantPermissions = (await _permissionGrantRepository
  24. .SelectListAsync(a => a.GrantType == "R" && CurrentUser.Roles.Contains(a.GrantValue), a => a.Permission))
  25. .Distinct().ToList();
  26. foreach (var group in result)
  27. {
  28. foreach (var permission in group.Permissions)
  29. {
  30. if (grantPermissions.Any(b => b == $"{group.Group}:{permission.Name}"))
  31. permission.IsGranted = true;
  32. else
  33. permission.IsGranted = false;
  34. }
  35. }
  36. }
  37. return new R<List<GetAllPermissionDto>>(result);
  38. }
  39. public async Task<R<List<GetAllPermissionDto>>> GetRolePermission(string RoleName)
  40. {
  41. var result = await GetAllDefinePermission();
  42. var grantPermissions = (await _permissionGrantRepository
  43. .SelectListAsync(a => a.GrantType == "R" && RoleName == a.GrantValue, a => a.Permission))
  44. .Distinct().ToList();
  45. foreach (var group in result)
  46. {
  47. foreach (var permission in group.Permissions)
  48. {
  49. if (grantPermissions.Any(b => b == $"{group.Group}:{permission.Name}"))
  50. permission.IsGranted = true;
  51. else
  52. permission.IsGranted = false;
  53. }
  54. }
  55. return new R<List<GetAllPermissionDto>>(result);
  56. }
  57. public async Task<R> UpdatePermission(UpdatePermissionDto dto)
  58. {
  59. if(dto.Type == "R")
  60. {
  61. var exsit = await _roleManager.RoleExistsAsync(dto.Value);
  62. if (!exsit)
  63. throw new BusinessException(ErrorCode.RoleNotExist, "RoleNotExist")
  64. .WithMessageDataData(dto.Value);
  65. }
  66. using (var tran = await UnitOfWork.BeginTransactionAsync())
  67. {
  68. await _permissionGrantRepository.DeleteAsync(a => a.GrantType == dto.Type && a.GrantValue == dto.Value);
  69. await _permissionGrantRepository.InsertManyAsync(dto.Permissions.Select(a=> new PermissionGrant
  70. {
  71. Id = GuidGenerator.Create(),
  72. GrantType = dto.Type,
  73. GrantValue = dto.Value,
  74. Permission = a
  75. }).ToList());
  76. await DistributedCache.SetAsync($"Permission:{dto.Type}:{dto.Value}", dto.Permissions);
  77. await tran.CommitAsync();
  78. }
  79. return new R();
  80. }
  81. private ValueTask<List<GetAllPermissionDto>> GetAllDefinePermission()
  82. {
  83. var result = MemoryCache.Get<List<GetAllPermissionDto>>("AllDefinePermission");
  84. if (result == null)
  85. {
  86. result = new List<GetAllPermissionDto>();
  87. var apiDescriptionGroupCollectionProvider = ServiceProvider.GetRequiredService<IApiDescriptionGroupCollectionProvider>();
  88. var apiDescriptionGroups = apiDescriptionGroupCollectionProvider.ApiDescriptionGroups.Items.SelectMany(group => group.Items)
  89. .Where(a => a.ActionDescriptor is ControllerActionDescriptor)
  90. .GroupBy(a => (a.ActionDescriptor as ControllerActionDescriptor).ControllerTypeInfo);
  91. foreach (var apiDescriptions in apiDescriptionGroups)
  92. {
  93. var permissionGroup = new GetAllPermissionDto();
  94. var controllerTypeInfo = apiDescriptions.Key;
  95. var controllerAllowAnonymous = controllerTypeInfo.GetAttribute<AllowAnonymousAttribute>();
  96. var controllerComment = _xmlCommentHelper.GetTypeComment(controllerTypeInfo);
  97. permissionGroup.Group = controllerTypeInfo.Name;
  98. permissionGroup.Summary = controllerComment;
  99. foreach (var apiDescription in apiDescriptions)
  100. {
  101. var method = controllerTypeInfo.GetMethod(apiDescription.ActionDescriptor.RouteValues["action"]);
  102. var actionAllowAnonymous = method.GetAttribute<AllowAnonymousAttribute>();
  103. var actionAuthorize = method.GetAttribute<AuthorizeAttribute>();
  104. if ((controllerAllowAnonymous == null && actionAllowAnonymous == null) || actionAuthorize != null)
  105. {
  106. var methodComment = _xmlCommentHelper.GetMethodComment(method);
  107. permissionGroup.Permissions.Add(new PermissionDto { Name = method.Name, Summary = methodComment });
  108. }
  109. }
  110. if (permissionGroup.Permissions.Count > 0)
  111. result.Add(permissionGroup);
  112. }
  113. MemoryCache.Set("AllDefinePermission", result);
  114. }
  115. return ValueTask.FromResult(result);
  116. }
  117. }
  118. }

控制器代码如下:

  1. namespace Wheel.Controllers
  2. {
  3. /// <summary>
  4. /// 权限管理
  5. /// </summary>
  6. [Route("api/[controller]")]
  7. [ApiController]
  8. public class PermissionManageController : WheelControllerBase
  9. {
  10. private readonly IPermissionManageAppService _permissionManageAppService;
  11. public PermissionManageController(IPermissionManageAppService permissionManageAppService)
  12. {
  13. _permissionManageAppService = permissionManageAppService;
  14. }
  15. /// <summary>
  16. /// 获取所有权限
  17. /// </summary>
  18. /// <returns></returns>
  19. [HttpGet()]
  20. public Task<R<List<GetAllPermissionDto>>> GetPermission()
  21. {
  22. return _permissionManageAppService.GetPermission();
  23. }
  24. /// <summary>
  25. /// 获取指定角色权限
  26. /// </summary>
  27. /// <returns></returns>
  28. [HttpGet("{role}")]
  29. public Task<R<List<GetAllPermissionDto>>> GetRolePermission(string role)
  30. {
  31. return _permissionManageAppService.GetRolePermission(role);
  32. }
  33. /// <summary>
  34. /// 修改权限
  35. /// </summary>
  36. /// <param name="dto"></param>
  37. /// <returns></returns>
  38. [HttpPut]
  39. public async Task<R> UpdatePermission(UpdatePermissionDto dto)
  40. {
  41. return await _permissionManageAppService.UpdatePermission(dto);
  42. }
  43. }
  44. }

通过读取XML注释文件,自动生成Controller和Action的注释名称。
将权限配置信息写入缓存,提供给PermissionChecker使用。
权限返回的结构如下:

  1. namespace Wheel.Services.PermissionManage.Dtos
  2. {
  3. public class GetAllPermissionDto
  4. {
  5. public string Group { get; set; }
  6. public string Summary { get; set; }
  7. public List<PermissionDto> Permissions { get; set; } = new ();
  8. }
  9. public class PermissionDto
  10. {
  11. public string Name { get; set; }
  12. public string Summary { get; set; }
  13. public bool IsGranted { get; set; }
  14. }
  15. }

使用Postman测试API,可以看到,获取了我们的权限信息列表,按照Controller分组,细分到每一个Action,summary是我们XML注释的内容。
image.png

到这我们就完成了权限管理的API。

轮子仓库地址https://github.com/Wheel-Framework/Wheel
欢迎进群催更。

image.png

原文链接:https://www.cnblogs.com/fanshaoO/p/17754156.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号