当前位置:网站首页>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
边栏推荐
- Pat grade a 1119 pre- and post order traversals (30 points)
- Daily question 2 12
- The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
- Performance of calling delegates vs methods
- Kuboard
- MySQL winter vacation self-study 2022 11 (9)
- [groovy] string (string type variable definition | character type variable definition)
- [luat-air105] 4.1 file system FS
- Simple use of devtools
- Cette ADB MySQL prend - elle en charge SQL Server?
猜你喜欢
Huawei MPLS experiment
The architect started to write a HelloWorld
Kbp206-asemi rectifier bridge kbp206
Qrcode: generate QR code from text
error Couldn‘t find a package.json file in “你的路径“
New interesting test applet source code_ Test available
v-if VS v-show 2.0
[software reverse analysis tool] disassembly and decompilation tool
De debugging (set the main thread as hidden debugging to destroy the debugging Channel & debugger detection)
端口,域名,协议。
随机推荐
[move pictures up, down, left and right through the keyboard in JS]
The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
Google Chrome CSS will not update unless the cache is cleared - Google Chrome CSS doesn't update unless clear cache
Kubernetes - identity and authority authentication
Necessary fonts for designers
040. (2.9) relieved
1. Five layer network model
Assembly - getting started
为什么腾讯阿里等互联网大厂诞生的好产品越来越少?
IPv6 experiment
This + closure + scope interview question
About MySQL database connection exceptions
FBO and RBO disappeared in webgpu
How rem is used
The architect started to write a HelloWorld
Kuboard
[Chongqing Guangdong education] 2777t green space planning reference questions of National Open University in autumn 2018
Pdf things
De debugging (set the main thread as hidden debugging to destroy the debugging Channel & debugger detection)
LeetCode 237. Delete nodes in the linked list