1、自定义鉴权 参考文档:https://learn.microsoft.com/zh-cn/aspnet/core/security/authorization/iard?view=aspnetcore-10.0
我的想法是通过自定义特性来实现对接口鉴权,所以需要先定义一个特性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 using Microsoft.AspNetCore.Authorization;namespace WebApi.Attributes { public class PermissionAuthorizeAttribute : AuthorizeAttribute , IAuthorizationRequirement , IAuthorizationRequirementData { public string PermissionCode { get ; set ; } public PermissionAuthorizeAttribute (string permissionCode ) { PermissionCode = permissionCode; } public IEnumerable<IAuthorizationRequirement> GetRequirements () { yield return this ; } } }
定义特性后,要创建自己的鉴权处理器,通过覆写 HandleRequirementAsync 来鉴权,如果没有 context.Succeed()就会返回 403 状态码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 using Microsoft.AspNetCore.Authorization;using Microsoft.EntityFrameworkCore;using Model.Database;using System.Security.Claims;using WebApi.Attributes;namespace WebApi.Handler { public class PermissionAuthorizationHandler : AuthorizationHandler <PermissionAuthorizeAttribute > { private readonly IServiceScopeFactory _scopeFactory; public PermissionAuthorizationHandler ( IServiceScopeFactory scopeFactory ) { _scopeFactory = scopeFactory; } protected override async Task HandleRequirementAsync (AuthorizationHandlerContext context, PermissionAuthorizeAttribute requirement ) { var roleClaims = context.User.FindAll(ClaimTypes.Role).ToList(); if (!roleClaims.Any()) { return ; } var roleNames = roleClaims.Select(c=>c.Value).ToList(); if (roleNames.Contains("SuperAdmin" )) { context.Succeed(requirement); return ; } using var scope = _scopeFactory.CreateScope(); var db = scope.ServiceProvider.GetRequiredService<EdgeDbContext>(); string requiredPermission = requirement.PermissionCode; bool hasPermission = await db.Roles.Where(r => roleNames.Contains(r.RoleName)).Join( db.RolePermissions, r => r.RoleId, rp => rp.RoleId, (r, rp) => rp.PermissionId) .Join( db.Permissions, rpId => rpId, p => p.PermissionId, (rpId, p) => p.Code) .AnyAsync(code => code == requiredPermission); if (hasPermission) { context.Succeed(requirement); } } } }
最后就是注册自定义鉴权处理器
1 2 3 builder.Services.AddSingleton<IAuthorizationHandler, PermissionAuthorizationHandler>();
使用方法如下
1 2 3 4 5 6 7 8 9 10 [HttpGet("OpenDoor" ) ] [PermissionAuthorize("DeviceType:AccessControl:Control" ) ] public string OpenDoor () { return "用户具有门禁控制器控制权限,允许开门" ; } [HttpGet("AddUser" ) ] [PermissionAuthorize("Action:User:Add" ) ] public string AddUser () { return "用户具有添加用户权限,已添加用户" ; }