当前位置:网站首页>ABP vNext microservice architecture detailed tutorial - distributed permission framework (Part 2)
ABP vNext microservice architecture detailed tutorial - distributed permission framework (Part 2)
2022-07-05 03:39:00 【Dotnet cross platform】
3
Common components
Add public class library Demo.Permissions, edit Demo.Permissions.csproj file , take <Project Sdk="Microsoft.NET.Sdk"> Change it to :
<Project Sdk="Microsoft.NET.Sdk.Web">
by Demo.Permissions Project add Nuget quote Volo.Abp.Core and Microsoft.AspNetCore.Http, And Application Demo.Identity.HttpApi.Client project .
stay Demo.Permissions Add permission relation enumeration PermissionRelation as follows :
namespace Demo.Permissions;
/// <summary>
/// Permission relation enumeration
/// </summary>
public enum PermissionRelation
{
/// <summary>
/// Need to meet at the same time
/// </summary>
And,
/// <summary>
/// Only need to meet any one
/// </summary>
Or,
}
stay Demo.Permissions Add CusPermissionAttribute characteristic , Used to mark the permissions required by the interface , as follows :
namespace Demo.Permissions;
/// <summary>
/// Custom permission features
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class CusPermissionAttribute : Attribute
{
/// <summary>
/// Authority code
/// </summary>
public string[] PermissionCode { get; }
/// <summary>
/// The relationship between permissions
/// </summary>
public PermissionRelation Relation { get; } = PermissionRelation.And;
/// <summary>
/// Constructors
/// </summary>
/// <param name="relation"> Permissions on the relationship between </param>
/// <param name="permissionCodes"> Authority code </param>
public CusPermissionAttribute(PermissionRelation relation,params string[] permissionCodes)
{
Relation = relation;
PermissionCode = permissionCodes;
}
/// <summary>
/// Constructors
/// </summary>
/// <param name="permissionCodes"> Authority code </param>
public CusPermissionAttribute(params string[] permissionCodes)
{
PermissionCode = permissionCodes;
}
}
One feature can declare multiple permission codes ,Relation Represents the relationship between all permission codes in this feature , If And, The user needs to have all the permission codes declared by this feature to pass the verification , if Or, It means that the user can pass the authentication as long as he has any one or more permissions declared in this feature .
An interface can declare multiple features , Between features is And Relationship .
stay Demo.Permissions Add permission verification Middleware in CusPermissionMiddleware as follows :
using Demo.Identity.Permissions;
using Microsoft.AspNetCore.Http.Features;
using Volo.Abp.Users;
namespace Demo.Permissions;
/// <summary>
/// Custom permission middleware
/// </summary>
public class CusPermissionMiddleware
{
private readonly RequestDelegate _next;
private readonly ICurrentUser _currentUser;
private readonly ISysPermissionAppService _service;
public CusPermissionMiddleware(RequestDelegate next, ICurrentUser currentUser, ISysPermissionAppService service)
{
_next = next;
_currentUser = currentUser;
_service = service;
}
public async Task InvokeAsync(HttpContext context)
{
var attributes =
context.GetEndpoint()?.Metadata.GetOrderedMetadata<CusPermissionAttribute>();
// If it doesn't exist CusPermissionAttribute Feature, the interface does not need permission verification , Just skip
if (attributes==null||attributes.Count==0)
{
await _next(context);
return;
}
// If permission authentication is required, it must be a logged in user , Otherwise return to 401
if (_currentUser.Id == null)
{
context.Response.StatusCode = 401;
return;
}
// Get user rights
var userPermisions = (await _service.GetUserPermissionCode((Guid) _currentUser.Id)).ToHashSet();
// Comparison authority If there is no permission, return 403
foreach (var cusPermissionAttribute in attributes)
{
var flag = cusPermissionAttribute.Relation == PermissionRelation.And
? cusPermissionAttribute.PermissionCode.All(code => userPermisions.Contains(code))
: cusPermissionAttribute.PermissionCode.Any(code => userPermisions.Contains(code));
if (!flag)
{
context.Response.StatusCode = 403;
return;
}
}
await _next(context);
}
}
When the interface is called , The middleware will obtain the permission characteristics declared by the interface , And call the identity management service interface to obtain the permission code held by the current user , Verify in order of characteristics .
stay Demo.Permissions Add PermissionRegistor class , It is used to read all permission codes declared in the code when the aggregation service is started , And register with the identity management service . The code is as follows :
using System.ComponentModel;
using Demo.Identity.Permissions.Dto;
namespace Demo.Permissions;
/// <summary>
/// Permission registration
/// </summary>
public static class PermissionRegistor
{
/// <summary>
/// Get the permission set in the specified type
/// </summary>
/// <param name="serviceName"> The service name </param>
/// <typeparam name="T"> type </typeparam>
/// <returns></returns>
internal static List<SysPermissionDto> GetPermissions<T>(string serviceName)
{
List<SysPermissionDto> result = new List<SysPermissionDto>();
Type type = typeof(T);
var fields = type.GetFields().Where(x=>x.IsPublic&&x.IsStatic);
foreach (var field in fields)
{
string code = field.GetValue(null).ToString();
string name = "";
object[] objs = field.GetCustomAttributes(typeof(DescriptionAttribute), false); // Get description properties
if (objs != null && objs.Length > 0)
{
DescriptionAttribute descriptionAttribute = (DescriptionAttribute) objs[0];
name = descriptionAttribute.Description;
}
string parentCode = null;
if (code.Contains("."))
{
parentCode = code.Substring(0, code.LastIndexOf('.'));
}
result.Add(new SysPermissionDto()
{
Name = name,
Code = code,
ParentCode = parentCode,
ServiceName = serviceName,
});
}
return result;
}
}
stay Demo.Permissions Add CusPermissionExtensions class , Provide IApplicationBuilder Extension method of , Used to register middleware and register permissions , The code is as follows :
using Demo.Identity.Permissions;
namespace Demo.Permissions;
public static class CusPermissionExtensions
{
/// <summary>
/// Register custom permissions
/// </summary>
public static void UseCusPermissions<T>(this IApplicationBuilder app, string serviceName)
{
app.RegistPermissions<T>(serviceName);
app.UseMiddleware<CusPermissionMiddleware>();
}
/// <summary>
/// Registration rights
/// </summary>
/// <param name="app"></param>
/// <param name="serviceName"> The service name </param>
/// <typeparam name="T"></typeparam>
private static async Task RegistPermissions<T>(this IApplicationBuilder app, string serviceName)
{
var service = app.ApplicationServices.GetService<ISysPermissionAppService>();
var permissions = PermissionRegistor.GetPermissions<T>(serviceName);
await service.RegistPermission(serviceName, permissions);
}
}
stay Demo.Permissions Add DemoPermissionsModule The categories are as follows :
using Demo.Identity;
using Volo.Abp.Modularity;
namespace Demo.Permissions;
[DependsOn(typeof(IdentityHttpApiClientModule))]
public class DemoPermissionsModule:AbpModule
{
}
4
Aggregation service layer
In the aggregation service layer , We can use the just created Demo.Permissions Class library , Take the mall service as an example .
stay Demo.Store.Application Add to the project Demo.Permissions Project references for , And for DemoStoreApplicationModule Class adds the following features :
[DependsOn(typeof(DemoPermissionsModule))]
stay Demo.Store.Application Added in the project PermissionLab Class is used to declare all permissions used in this service , The code is as follows
using System.ComponentModel;
namespace Demo.Store.Application;
/// <summary>
/// Permission list
/// </summary>
public class PermissionLab
{
[Description(" Order ")]
public const string ORDER = "Order";
[Description(" Create order ")]
public const string ORDER_CREATE = $"{ORDER}.Create";
[Description(" Query order ")]
public const string ORDER_SELECT = $"{ORDER}.Select";
// Add other permissions ……
}
Here we use constants to define permissions , The value of the constant is the permission code , Constant names use Description Characteristic marks .
stay Demo.Store.HttpApi.Host Project profile appsettings.json Medium RemoteServices Add the following address of identity management service in :
"Default": {
"BaseUrl": "http://localhost:5000/"
},
stay Demo.Store.HttpApi.Host project DemoStoreHttpApiHostModule class OnApplicationInitialization Method app.UseRouting(); , Add the following after it :
app.UseCusPermissions<PermissionLab>("Store");
In this way, we can aggregate the service layer ApplicationService Add CusPermission Used to declare the permissions required by the interface , for example :
/// <summary>
/// Query the order list in pages
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
[CusPermission(PermissionLab.ORDER_SELECT)]
public async Task<PagedResultDto<StoreOrderDto>> GetListAsync(PagedAndSortedResultRequestDto input)
{
var ret = await _orderAppService.GetListAsync(input);
return new PagedResultDto<StoreOrderDto>
{
TotalCount = ret.TotalCount,
Items = ObjectMapper.Map<IReadOnlyList<OrderDto>, List<StoreOrderDto>>(ret.Items)
};
}
5
Additional explanation
After completing the above steps , We can aggregate the service layer Admin The project encapsulates and exposes the role permission related interface in the identity management service to the client call , The registration permission interface is only used to register permissions for the aggregation service layer , It is not recommended to expose to clients .
Here I simply use the verification of the permission code itself , There is no correlation verification of parent-child relationship , In the actual project , It can be modified or extended as needed .
end
More exciting
Follow me to get
边栏推荐
- 【做题打卡】集成每日5题分享(第三期)
- VM in-depth learning (XXV) -class file overview
- Port, domain name, protocol.
- Anchor free series network yolox source code line by line explanation four (a total of ten, ensure line by line explanation, after reading, you can change the network at will, not just as a participan
- speed or tempo in classical music
- Flex flexible layout
- Flume configuration 4 - customize mysqlsource
- 天干地支纪年法中为什么是60年一个轮回,而不是120年
- Delphi free memory
- De debugging (set the main thread as hidden debugging to destroy the debugging Channel & debugger detection)
猜你喜欢
KVM virtualization
Multimedia query
The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
Learning notes of raspberry pie 4B - IO communication (I2C)
函数基础学习02
An elegant program for Euclid‘s algorithm
Azkaban installation and deployment
[system security] ten thousand words summary system virtualization container bottom layer principle experiment
Class inheritance in C #
[wp]bmzclub几道题的writeup
随机推荐
The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
This + closure + scope interview question
De debugging (set the main thread as hidden debugging to destroy the debugging Channel & debugger detection)
程序员的视力怎么样? | 每日趣闻
花了2晚,拿到了吴恩达@斯坦福大学的机器学习课程证书
Usage scenarios and solutions of ledger sharing
KVM virtualization
【软件逆向-基础知识】分析方法、汇编指令体系结构
Performance of calling delegates vs methods
Kuboard
[wp][入门]刷弱类型题目
DECLARE_ WAIT_ QUEUE_ HEAD、wake_ up_ Interruptible macro analysis
Tencent cloud, realize image upload
How to define a unified response object gracefully
[system security] ten thousand words summary system virtualization container bottom layer principle experiment
UE4 DMX和grandMA2 onPC 3.1.2.5的操作流程
[105] Baidu brain map - Online mind mapping tool
Unity implements the code of the attacked white flash (including shader)
Accuracy problem and solution of BigDecimal
When sqlacodegen generates a model, how to solve the problem that the password contains special characters?