当前位置:网站首页>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
边栏推荐
- [untitled]
- De debugging (set the main thread as hidden debugging to destroy the debugging Channel & debugger detection)
- [groovy] loop control (number injection function implements loop | times function | upto function | downto function | step function | closure can be written outside as the final parameter)
- 深度学习——LSTM基础
- Qrcode: generate QR code from text
- [learning notes] month end operation -gr/ir reorganization
- 問下,這個ADB mysql支持sqlserver嗎?
- Smart pointer shared_ PTR and weak_ Difference of PTR
- [wp][入门]刷弱类型题目
- SQL performance optimization skills
猜你喜欢
[vérification sur le Web - divulgation du code source] obtenir la méthode du code source et utiliser des outils
grandMA2 onPC 3.1.2.5的DMX参数摸索
IPv6 experiment
Hot knowledge of multithreading (I): introduction to ThreadLocal and underlying principles
Class inheritance in C #
Port, domain name, protocol.
[groovy] loop control (number injection function implements loop | times function | upto function | downto function | step function | closure can be written outside as the final parameter)
[2022 repair version] community scanning code into group activity code to drain the complete operation source code / connect the contract free payment interface / promote the normal binding of subordi
Jd.com 2: how to prevent oversold in the deduction process of commodity inventory?
The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
随机推荐
汇编-入门
Usage scenarios and solutions of ledger sharing
How rem is used
深度学习——LSTM基础
ICSI213/IECE213 Data Structures
[positioning in JS]
[move pictures up, down, left and right through the keyboard in JS]
为什么腾讯阿里等互联网大厂诞生的好产品越来越少?
SQL performance optimization skills
The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
Sqoop command
Assembly - getting started
[vérification sur le Web - divulgation du code source] obtenir la méthode du code source et utiliser des outils
[software reverse analysis tool] disassembly and decompilation tool
【web審計-源碼泄露】獲取源碼方法,利用工具
Pat class a 1160 forever (class B 1104 forever)
NPM introduction link symbolic link
[Chongqing Guangdong education] 2777t green space planning reference questions of National Open University in autumn 2018
[untitled]
问下,这个ADB mysql支持sqlserver吗?