ASP.NET 多个范围的核心 ClaimsAuthorizationRequirement 未按预期工作?

ASP.NET Core ClaimsAuthorizationRequirement for multiple scopes not working as intended?

我遇到了一些事情,如果这是有意为之的行为或主要的安全风险,想征求您的意见。

我打算做的是授权两个 API 具有不同策略的控制器操作。一个策略需要一个范围,另一个策略需要两个范围。

因此我定义了范围

我打算授权的控制器以及授权方式如下:

  [ApiController]
  [Route("api/v1/[controller]")]
  //intentionally no authorize here
  public class TestContoller : ControllerBase 
  {

    [HttpGet("single")]
    [Authorize(AuthenticationSchemes = "Bearer", Policy = nameof(SingleScopePolicy))]
    public IActionResult GetSingle() { return Ok("success"); }

    [HttpGet("double")]
    [Authorize(AuthenticationSchemes = "Bearer", Policy = nameof(DoubleScopePolicy))]
    public IActionResult GetDouble() { return Ok("success"); }

  }

预期的行为(据我现在理解)是当 SingleScopePolicy 检测到它没有 scope:1 并且 DoubleScopePolicy 检测到它没有 scope:1 时 returns 禁止 ANDscope:2。 AND 是相关部分!

在 Startup.cs 中,我配置了授权并添加了类似的范围(故意没有用于测试的默认策略)

public void ConfigureService(IServiceCollection service) 
  {
    // ...

    services.AddAuthorization
    (
      options =>
      {
        options.AddPolicy(nameof(SingleScopePolicy), new SingleScopePolicy());
        options.AddPolicy(nameof(DoubleScopePolicy), new DoubleScopePolicy());
      }
    );

    // ...
  }

我通过代码定义了我的两个策略:

  public class SingleScopePolicy : AuthorizationPolicy
  {
    public SingleScopePolicy() : base 
    (
      new IAuthorizationRequirement[]
      {
        new ClaimsAuthorizationRequirement("scope", new string[] { "scope:1 })
      },
      new string[] { "Bearer" }
    ) { }
  }

  public class DoubleScopePolicy : AuthorizationPolicy
  {
    public DoubleScopePolicy() : base 
    (
      new IAuthorizationRequirement[]
      {

        // does not work (never returns forbid)
        //new ClaimsAuthorizationRequirement("scope", new string[] { "scope:1", "scope:2" }) 

        // works
        new ClaimsAuthorizationRequirement("scope", new string[] { "scope:1" }),
        new ClaimsAuthorizationRequirement("scope", new string[] { "scope:2" }),
      },
      new string[] { "Bearer" }
    ) { }
  }

我现在的问题是在 DoubleScopePolicy 中声明授权要求是否有效,或者是否有意使其无效。

实际上从不 returns 禁止使用下面的行,并且始终允许访问。这让我惊叹,因为它为您提供了一个字符串 [],我将其理解为 "hey, give me two and I will check there are both"。如果我在两行中单独定义它,它会按预期工作(由我)。

new ClaimsAuthorizationRequirement("scope", new string[] { "scope:1", "scope:2" }) 

ClaimsAuthorizationRequirementsource 显示 AllowedValues 属性 被视为 操作:

found = context.User.Claims.Any(
    c => string.Equals(c.Type, requirement.ClaimType, StringComparison.OrdinalIgnoreCase)
          && requirement.AllowedValues.Contains(c.Value, StringComparer.Ordinal));

// ...

if (found)
{
    context.Succeed(requirement);
}

如您所述,您可以添加多个 ClaimsAuthorizationRequirement 以便将检查视为 操作。