gpt4 book ai didi

asp.net-core-2.0 - ASP.NET Core 授权 : Combining OR requirements

转载 作者:行者123 更新时间:2023-12-01 12:14:21 25 4
gpt4 key购买 nike

我不确定如何在 ASP.NET Core Authorization 中实现组合的“OR”要求。在以前版本的 ASP.NET 中,这本来是用角色来完成的,但我试图用声明来做到这一点,部分是为了更好地理解它。

用户有一个名为 AccountType 的枚举,它将提供对 Controller /操作/等的不同级别的访问。共有三个级别的类型,分别称为 User、BiggerUser 和 BiggestUser。所以 BiggestUser 可以访问他们下面的帐户类型所拥有的一切等等。我想通过使用策略的授权标签来实现这一点。

所以首先我有一个要求:

public class TypeRequirement : IAuthorizationRequirement
{
public TypeRequirement(AccountTypes account)
{
Account = account;
}

public AccountTypes Account { get; }
}

我创建策略:

services.AddAuthorization(options =>
{
options.AddPolicy("UserRights", policy =>
policy.AddRequirements(new TypeRequirement(AccountTypes.User));
});

通用处理程序:

public class TypeHandler : AuthorizationHandler<TypeRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TypeRequirement requirement)
{
if (!context.User.HasClaim(c => c.Type == "AccountTypes"))
{
context.Fail();
}

string claimValue = context.User.FindFirst(c => c.Type == "AccountTypes").Value;
AccountTypes claimAsType = (AccountTypes)Enum.Parse(typeof(AccountTypes), claimValue);
if (claimAsType == requirement.Account)
{
context.Succeed(requirement);
}

return Task.CompletedTask;
}
}

我要做的是在政策中添加多个要求,其中任何一个都可以满足它。但我目前的理解是,如果我做这样的事情:

options.AddPolicy("UserRights", policy => policy.AddRequirements(
new TypeRequirement(AccountTypes.User),
new TypeRequirement(AccountTypes.BiggerUser)
);

这两个要求都必须满足。如果 AddRequirements 中有某种方式指定 OR 条件,我的处理程序将起作用。那么我是在正确的轨道上还是有其他更有意义的方法来实现这一点?

最佳答案

官方文档有dedicated section当您想要实现 OR 逻辑时。他们提供的解决方案是针对一项要求注册多个授权处理程序。在这种情况下,所有处理程序都会运行,如果至少有一个处理程序成功,则认为满足要求。

不过,我认为该解决方案不适用于您的问题;我可以看到两种很好地实现这一点的方法

提供多个AccountTypesTypeRequirement
然后,要求将保存满足要求的所有值。

public class TypeRequirement : IAuthorizationRequirement
{
public TypeRequirement(params AccountTypes[] accounts)
{
Accounts = accounts;
}

public AccountTypes[] Accounts { get; }
}

然后处理程序验证当前用户是否与定义的帐户类型之一匹配

public class TypeHandler : AuthorizationHandler<TypeRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TypeRequirement requirement)
{

if (!context.User.HasClaim(c => c.Type == "AccountTypes"))
{
context.Fail();
return Task.CompletedTask;
}

string claimValue = context.User.FindFirst(c => c.Type == "AccountTypes").Value;
AccountTypes claimAsType = (AccountTypes)Enum.Parse(typeof(AccountTypes),claimValue);
if (requirement.Accounts.Any(x => x == claimAsType))
{
context.Succeed(requirement);
}

return Task.CompletedTask;
}
}

这允许您创建多个使用相同要求的策略,除非您可以定义 AccountTypes 的有效值。对于他们每个人

options.AddPolicy(
"UserRights",
policy => policy.AddRequirements(new TypeRequirement(AccountTypes.User, AccountTypes.BiggerUser, AccountTypes.BiggestUser)));

options.AddPolicy(
"BiggerUserRights",
policy => policy.AddRequirements(new TypeRequirement(AccountTypes.BiggerUser, AccountTypes.BiggestUser)));

options.AddPolicy(
"BiggestUserRights",
policy => policy.AddRequirements(new TypeRequirement(AccountTypes.BiggestUser)));

使用枚举比较功能

正如您在问题中所说,您对待 AccountTypes 的不同值的方式存在层次结构。 :
  • User可以访问一些东西;
  • BiggerUser可以访问所有内容 User可以访问,以及其他一些东西;
  • BiggestUser可以访问所有内容

  • 想法是,要求将定义 AccountTypes 的最低值。必须满足,然后处理程序会将其与用户的帐户类型进行比较。

    枚举可以与 <= 进行比较。和 >=运算符,也使用 CompareTo方法。我无法快速找到关于此的可靠文档,但是 this code sample on docs.microsoft.com显示低于或等于运算符的用法。

    要利用此功能,枚举值需要与您期望的层次结构相匹配,例如:

    public enum AccountTypes
    {
    User = 1,
    BiggerUser = 2,
    BiggestUser = 3
    }

    或者

    public enum AccountTypes
    {
    User = 1,
    BiggerUser, // Automatiaclly set to 2 (value of previous one + 1)
    BiggestUser // Automatically set to 3
    }

    需求、处理程序和策略声明的代码将如下所示:

    public class TypeHandler : AuthorizationHandler<TypeRequirement>
    {
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TypeRequirement requirement)
    {

    if (!context.User.HasClaim(c => c.Type == "AccountTypes"))
    {
    context.Fail();
    return Task.CompletedTask;
    }

    string claimValue = context.User.FindFirst(c => c.Type == "AccountTypes").Value;
    AccountTypes claimAsType = (AccountTypes)Enum.Parse(typeof(AccountTypes),claimValue);
    if (claimAsType >= requirement.MinimumAccount)
    {
    context.Succeed(requirement);
    }

    return Task.CompletedTask;
    }
    }

    options.AddPolicy(
    "UserRights",
    policy => policy.AddRequirements(new TypeRequirement(AccountTypes.User)));

    options.AddPolicy(
    "BiggerUserRights",
    policy => policy.AddRequirements(new TypeRequirement(AccountTypes.BiggerUser)));

    options.AddPolicy(
    "BiggestUserRights",
    policy => policy.AddRequirements(new TypeRequirement(AccountTypes.BiggestUser)));

    关于asp.net-core-2.0 - ASP.NET Core 授权 : Combining OR requirements,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49389970/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com