asp.net core 2.2 如何制作一个可以调用数据库来检查用户声明以授权用户的中间件

How to make a middleware that can call database to check user claims to authorize a user in asp.net core 2.2

在 asp.net 核心 2.2 中制作中间件的最佳实践或实现中间件的正确方法是什么。

我的场景是 我在 asp.net 核心 2.2 中构建了一个网络 api,我在我的控制器中实现了类似这样的授权 [Authorize(Policy = "UserDelete")] UserDelete 是一个用户声明 我的问题是我有很多用户声明如果我将此声明保存在 JWT 中,用户是否可以拥有或多或少多达 20 个声明,这可能会导致 JWT 的大小过大,我想做的就是调用声明或创建一个中间件来调用此声明的数据库,以便我只需要保存在 JWT 中的是用户凭据。

您只需要创建一个 AuthorizationHandler,请按照说明操作: 1- 创建一个 class 并将其命名为 MinimumPermissionHandler 或其他名称。将以下代码复制并粘贴到其中:

public class MinimumPermissionRequirement : IAuthorizationRequirement { }

public class MinimumPermissionHandler : AuthorizationHandler<MinimumPermissionRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MinimumPermissionRequirement requirement)
    {
        if (!(context.Resource is AuthorizationFilterContext filterContext))
        {
            context.Fail();
            return Task.CompletedTask;
        }

        //check if token has subjectId
        var subClaim = context.User?.Claims?.FirstOrDefault(c => c.Type == "sub");
        if (subClaim == null)
        {
            context.Fail();
            return Task.CompletedTask;
        }

        //check if token is expired
        var exp = context.User.Claims.FirstOrDefault(c => c.Type == "exp")?.Value;
        if(exp == null || new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(long.Parse(exp)).ToLocalTime() < DateTime.Now)
        {
            context.Fail();
            return Task.CompletedTask;
        }

        //other checkpoints
        //your db functions to check if user has desired claims

        context.Succeed(requirement);
        return Task.CompletedTask;
    }
}

2- 定义一个策略并将处理程序添加到服务中,所以将这行放在您的 Startup class:

public void ConfigureServices(IServiceCollection services)
{
   //deleted extra lines for brevity 
   services.AddAuthorization(options =>
   {
      options.AddPolicy("AccessControl", policy =>
      {
           policy.RequireAuthenticatedUser();
           policy.AddRequirements(new MinimumPermissionRequirement());
      });
   });
   //injection
   services.AddScoped<IAuthorizationHandler, MinimumPermissionHandler>();
}

3- 最后,为了检查访问权限,只需将此代码放在控制器上方

[Authorize(Policy = "AccessControl")]