MVC Core Web API中的自定义JWT令牌授权

时间:2016-09-26 09:26:53

标签: authentication asp.net-core asp.net-core-middleware

我一直在实现自己的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令牌中的Claim),然后从基于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>();

然后在Controller中:

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

   // AND

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

哪个工作符合预期(如果未将功能分配给用户,则返回403)

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

0 个答案:

没有答案