【问题标题】:Hierarchical policies / requirements in ASP.NET Core IdentityASP.NET Core Identity 中的分层策略/要求
【发布时间】:2017-10-25 20:51:35
【问题描述】:

我刚刚开始使用 ASP.NET Core Identity 并定义了以下要求:

public sealed class IsCustomerUserRequirement : IAuthorizationRequirement

public sealed class IsSuperUserRequirement : IAuthorizationRequirement

使用以下基本处理程序:

public class IsCustomerUserHandler : AuthorizationHandler<IsCustomerUserRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IsCustomerUserRequirement requirement)
    {
        if (context.User.HasClaim(_ => _.Type == "customer"))
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

public class IsSuperUserHandler : AuthorizationHandler<IsSuperUserRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IsSuperUserRequirement requirement)
    {
        if (context.User.IsInRole("super_user"))
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

然后我可以将这些放在基本政策中:

        services
            .AddAuthorization(options =>
            {
                options.AddPolicy("MustBeSuperUser", policy => policy.Requirements.Add(new IsSuperUserRequirement()));
                options.AddPolicy("CustomersOnly", policy => policy.Requirements.Add(new IsCustomerUserRequirement()));
            });

并使用[Authorize("CustomersOnly")] 应用它,效果很好。

我的要求是能够允许超级用户声明具有super_user 角色但没有 customer 声明的主体,也可以访问仅限客户的区域。

我目前已通过将处理程序更改为手动检查来实现这一点:

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IsCustomerUserRequirement requirement)
    {
        if (context.User.HasClaim(_ => _.Type == Claims.Customer) ||
            context.User.IsInRole(Roles.SuperUser))
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }

我的问题感觉好像我没有抓住重点。有没有更好的方法来定义这个,所以我以后不必在每个处理程序中重复超级用户检查?


这一切的大局是我使用 IdentityServer4 (ASP.NET Identity-backed) 进行身份验证,然后打算使用一些基于 JWT 的声明(一个声明,两个角色)来进一步识别用户授权属于特定于应用程序角色/权限结构和一些与 Identity Server 无关的自定义中间件。围绕该主题有哪些最佳实践(如果有)?

【问题讨论】:

  • 我发现在 netcore 中基于策略的新授权方式在进行细粒度授权时有点不友好。我们最终实现了一个自定义操作过滤器(继承 IAsyncActionFilter)来处理授权,并且比使用那些需要在启动时设置的策略提供更多的灵活性。由于用户拥有的声明的简单变化,人们不希望拥有相同策略的 X 个变体。
  • @scheien 如果同一策略有多个变体,则说明您使用的策略和要求不正确。一个策略应该需要一组要求。这些要求可以(单独地)通过各种索赔组合来满足,然后由需求处理程序来解决。但这不会使政策更加复杂。 – 随意发布一个问题,概述您的具体情况,我也许可以帮助您简化它以适应新模型。 ASP.NET Core 身份验证堆栈实际上非常干净且功能强大。

标签: c# asp.net-core-identity


【解决方案1】:

“这感觉就像我错过了重点” – 是的,在某种程度上你错过了重点。您正在执行基于角色的授权:用户可以是客户或超级用户。

但是,新模型是基于声明的授权,其中用户对某事有声明,而您正在使用它来授权他们。因此,理想情况下,超级用户将获得与客户相同的声明,并允许以这种方式访问​​资源。这样的声明也不会被称为customer,而是属于用户的财产。

您仍然可以将基于角色的授权模型与声明一起使用,但您应该避免混合它们。正如您自己注意到的那样,这最终会变得有点奇怪。

话虽如此,有多种方法可以使用不同的要求来使策略成功。如果您只使用角色(而不是 customer 声明),您可以简单地使用内置方式:

options.AddPolicy("MustBeSuperUser", policy => policy.RequireRole("super_user"));
options.AddPolicy("CustomersOnly", policy => policy.RequireRole("customer", "super_user"));

这样,CustomersOnly 策略将由customersuper_user 角色来实现。

由于您没有为客户使用角色,因此您必须在此处遵循您的要求实施。但是,授权要求的工作方式是,您可以为同一要求类型设置多个处理程序,并且只有其中一个需要成功(只要没有一个失败),要求才能成功。

因此您可以让您的IsSuperUserHandler 处理多个需求。您可以按照AuthorizationHandler&lt;T&gt; 的实现来完成这项工作:

public class IsSuperUserHandler : IAuthorizationHandler
{
    public virtual async Task HandleAsync(AuthorizationHandlerContext context)
    {
        foreach (var req in context.Requirements)
        {
            if (req is IsSuperUserRequirement || req is IsCustomerUserRequirement)
            {
                if (context.User.IsInRole("super_user"))
                    context.Succeed(req);
            }
        }
    }
}

所以您的IsSuperUserHandler 现在是IsSuperUserRequirementIsCustomerUserRequirement 的授权处理程序。因此,对于超级用户而言,需要 IsCustomerUserRequirementCustomersOnly 策略也将得到满足。

【讨论】:

  • customer 是声明的原因是因为它具有客户 ID 的值(用户与客户相关联,是其身份的一部分)。由于多重继承,关于IsSuperUserHandler 的最终解决方案将不起作用。我确实尝试将这两个要求添加到策略中,但这并没有按预期工作(我的处理程序都没有显式失败,但它仍然不满足策略)。我不想将所有声明都放入用户令牌中,我的声明最终将成为细粒度权限的同义词:-(
  • 我同意你的主要观点,我的脱节感觉是因为我混合了两个概念。
  • 对不起,出于某种原因,我认为需求处理程序是一个接口。编辑了我的答案以包含一个明确处理这两种需求类型的实际授权处理程序。 – 向同一策略添加多个要求意味着必须满足所有这些要求。没有办法让政策有分离的要求。
  • 好的,谢谢。是的,这似乎对每个策略的多个要求有意义,我对“多个处理程序”支持感到困惑。我需要离开并考虑一下。我试图将 Identity Server 保持在最低限度,没有特定于应用程序的内容,没有授权内容(或很少)。我对这些技术中的大多数都是新手,所以在黑暗中摸索了一下,几乎每一次转弯都会让电线交叉,哈哈
  • 我将把它标记为已接受,因为它突出了我正在做的授权工作的问题。将阅读有关基于声明的身份验证和重置的 MSDN 文档。
猜你喜欢
  • 1970-01-01
  • 2017-02-11
  • 1970-01-01
  • 2022-10-30
  • 1970-01-01
  • 2020-07-09
  • 1970-01-01
  • 2020-06-15
  • 1970-01-01
相关资源
最近更新 更多