我一直在实现我自己的JWT令牌 Authentication/Authorisation ,而不使用Identity等 .

基于这些链接,我成功创建了一个JWT令牌 - 并使用属性 [Authorize] 实现了授权

Token Authentication 1

Token Authentication 2 - [我的代码与此完全相同]

我遇到的问题是,在我正在处理的应用程序中,授权基于 FEATURE 而不是 ROLE .

这是DB Schema

1. User
-------------------
   UserId (PK)

2. Role 
-------------------
   RoleId (PK)


3. RoleFeatures
-------------------
   (RoleId PK, FK)
   (FeatureId PK, FK)

4. Features
-------------------
   FeatureId (PK)

角色不是预定义的,但功能是预先定义的,例如创建用户,更新用户

假设我们有2个角色 "User Manager""User and Customer Admin" - 来自这两个角色的用户都可以 Create, Update and Delete 用户 .

现在在Application Controller中而不是做

[Authorise(Roles="User Manager, User and Customer Admin")]
   public IActionResult CreateUser()

我需要这个:

[Authorise(Features="Create User")]
   public IActionResult CreateUser()

我如何在MVC Core Web API中实现这种类型的JWT令牌授权?

一种方法是将JWT令牌中的功能保存为声明 - 但问题是角色可以说20个功能,并将它们保存在令牌中会显着增加令牌大小 -

所以我需要的是授权属性的自定义实现,它获取来自JWT令牌的userId(userId是JWT令牌中的声明),然后从基于UserId的DB获取角色特征并应用授权 .

编辑

基于.NET核心文档 - 我发现我可以创建一个策略

https://docs.asp.net/en/latest/security/authorization/policies.html

所以我继续创建了需求和需求处理程序,如下所示:

public class FeatureRequirement : IAuthorizationRequirement
{
    public string FeatureName { get; set; }

    public FeatureRequirement(string featureName) { FeatureName = featureName; }
}

public class FeatureRequirementHandler : AuthorizationHandler<FeatureRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FeatureRequirement requirement)
    {
        var userId = context.User.Claims.FirstOrDefault(s => s.Type == "UserId");

        if (userId == null) { return Task.FromResult(0); }

        //TODO: Get User Features from DB based on UserId
        var userFeatures = new List<string> { "Create User", "Update User" };

        if (userFeatures.Contains(requirement.FeatureName))
        {
            context.Succeed(requirement);
        }
        return Task.FromResult(0);
    }
}

在Startup.cs中

services.AddAuthorization(options =>
     {
      // Create the Policies
      // Problem here have to define a policy for each feature 

       options.AddPolicy("Create User", policy => policy.Requirements.Add(new FeatureRequirement("Create User")));

       options.AddPolicy("Update User", policy => policy.Requirements.Add(new FeatureRequirement("Update User")));

     });

    services.AddScoped<IAuthorizationHandler, FeatureRequirementHandler>();

然后在控制器中:

[Authorise(Policy="Create User")]
   public IActionResult CreateUser()

   // AND

   [Authorise(Policy="Update User")]
   public IActionResult UpdateUser()

哪个按预期工作(如果没有为用户分配功能,则返回403)

问题在于我必须为每个功能创建一个新策略 - 有更好的方法吗?