首页 > 解决方案 > 使用 JWT 的 aspcore 多策略

问题描述

我有两项政策,即 ApiUser 和 CompanyBased。当我使用基于公司的策略 ([Authorize(Policy = "CompanyBased")] ) 时,应用程序无法验证 JWT 令牌。当我使用 [Authorize] 时,它运行良好,令牌得到验证......

版本:核心 2.2

Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] 授权失败。Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3] 过滤器“Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter”处的请求授权失败。Microsoft.AspNetCore.Mvc.ForbidResult[1] 使用身份验证方案执行 ForbidResult ()。Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[13] AuthenticationScheme:承载被禁止。

        // api user claim policy
        services.AddAuthorization(options =>
        {
            options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
            options.AddPolicy("CompanyBased", policy =>
            {
                policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess);
                policy.AddRequirements(new CompanyBasedRequirement());
            });
        });

这是 CompanyBasedHandler

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CompanyBasedRequirement requirement)
{
    #region Validate Company id

    Guid? companyId = _httpContextAccessor.HttpContext.Request.Headers.GetCompanyId();
    string nameIdentifier = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
    if (companyId is null)
    {
        _logger.LogInformation($"No company suppied for {nameIdentifier}");
        context.Fail();
    }
    else
    {
        if (!_clientRepository.IsClientValid(companyId.Value, nameIdentifier))
        {
            _logger.LogInformation($"{companyId} does not belong to {nameIdentifier}");
            context.Fail();
        }
        else
        {
            context.Succeed(requirement);
        }
    }

    #endregion Validate Company id

    return Task.CompletedTask;
}
  1. 如何确保 CompanyBased 验证 JWT 令牌
  2. 我可以用 await 使 HandleRequirementAsync 异步吗,我被 return await Task.CompletedTask 卡住了(这不起作用)!

标签: c#asp.net-core

解决方案


确保您在 Startup 类的依赖注入容器中正确注册了自定义授权处理程序。它应该注册为单例:

services.AddSingleton<IAuthorizationHandler, CompanyBasedHandler>();

您可以HandleRequirementAsync通过将方法签名更改为async Task然后在方法结束时不返回已完成的任务来进行异步/等待,例如:

protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, CompanyBasedRequirement requirement)
{
    #region Validate Company id

    Guid? companyId = _httpContextAccessor.HttpContext.Request.Headers.GetCompanyId();
    string nameIdentifier = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
    if (companyId is null)
    {
        _logger.LogInformation($"No company suppied for {nameIdentifier}");
        context.Fail();
    }
    else
    {
        if (!_clientRepository.IsClientValid(companyId.Value, nameIdentifier))
        {
            _logger.LogInformation($"{companyId} does not belong to {nameIdentifier}");
            context.Fail();
        }
        else
        {
            context.Succeed(requirement);
        }
    }

    #endregion Validate Company id
}

请注意,您没有在方法中执行任何异步操作,这意味着它将同步运行,因此不需要使此方法异步。


推荐阅读