1

我刚刚使用基于声明的授权实现了一个 web api。用户可以登录系统,然后根据用户可以执行的操作从数据库中提取一组声明并添加到 httpContext.User.Identity。

在 Startup.cs 中注册策略后,使用以下内容:

services.AddAuthorization(options =>
{
    options.AddPolicy(PoliciesDefinitions.RequiresVehicleList, policy => policy.RequireClaim(Permissions.VehiclesList.ToString()));

    ...               
});

我可以在要授权的控制器方法上使用 Authorize 属性,例如:

Authorize(Policy=PoliciesDefinitions.RequiresDriversList)]
[HttpGet]
public ActionResult Get() { ... }

这工作正常,但今天我更彻底地阅读了微软文档,我在基于声明的授权文档中遇到了这个声明:

声明是一个名称值对,表示主题是什么,而不是主题可以做什么

目前,我正在做 microsfot 建议不要做的事情。我正在将用户可以执行的操作(权限)添加到 identity 中。所以,这让我想,我做错了吗?如果答案是肯定的,您将在哪里存储用户权限以及授权如何工作?

4

1 回答 1

0

这允许 KVP 和多个值。

// with Razor, you did not specific if it was core 2, 3.1 or Razor

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("Vendors", policy =>
                          policy.RequireClaim("Type.Tykt.org", "Dealer", "Driver", "WholeSaler", "Asset", "Repair"));
    });
}

选项 2:

还有一个claims集合,用户成功登录后可以添加。

var user = new User {
  Email = "xyz@tykt.org",
  Name =  "xyz"
}

user.Claims.Add(new IdentityUserClaim<string> 
{ 
    ClaimType="your-type",   // your key
    ClaimValue="your-value"  // your value
});

await userManager.CreateAsync(user);

更新参考 MSDN

如果我理解了这个问题,那么您对如何存储检索确实是您的选择,那么您的问题就是索赔的价值。

通常,映射和验证以类似于 PermissionHandler : IAuthorizationHandler或通用方法的方式发生MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>。其中,加载值,并处理特定权限的需求验证,例如最小年龄,但实际声明(您在说明什么/min age policy 值通常在数据库中,如 DOB= 1/1/1990)随Principal对象一起移动。现在,您选择在哪里检索索赔的价值取决于您

在下面的函数中,他从 Context 中获取 Key 的值,然后进行验证

public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                   MinimumAgeRequirement requirement)
    {
        if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth &&
                                        c.Issuer == "http://contoso.com"))
        {
            return Task.CompletedTask;
        }

        var dateOfBirth = Convert.ToDateTime(
            // He gets the value on the server-side from any store or 3rd party relayer
            context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth && 
                                        c.Issuer == "http://contoso.com").Value);

        int calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
        if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
        {
            calculatedAge--;
        }

        if (calculatedAge >= requirement.MinimumAge)
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}
于 2020-04-13T22:24:32.880 回答