如何使用 Web Api Asp.Net Core 实现基于声明的授权?

Posted

技术标签:

【中文标题】如何使用 Web Api Asp.Net Core 实现基于声明的授权?【英文标题】:How to implement Claim based authorization using Web Api Asp.Net Core? 【发布时间】:2020-11-16 16:05:48 【问题描述】:

我正在使用 Web API 并在登录时生成 JWT 令牌。我对用户角色和声明有非常复杂的要求。一个用户可以有多个角色。一个角色可以有多个声明,而一个用户可以有特定的声明。我正在使用 Asp.Net Core Identity。一个用户可以在 AspNetUserClaims 中拥有数据,同一用户可以拥有不同的角色,并且每个角色在 AspRoleClaims 中都有声明。我已经使用 web api 成功实现了基于角色的授权,但是如何在 web API 中实现基于声明的授权?

我已经实现但不太喜欢的一件事是,我将所有用户声明(包括角色中的声明)存储在 JWT 令牌中,并且在每个请求中,我都从 JWT 中提取声明。但这是否是最佳实践 - 在 JWT 令牌中存储大数据?

或者在 Web API Dot Net 核心中进行基于声明的授权的其他方法是什么?

【问题讨论】:

【参考方案1】:

您可以像这样创建自定义策略,您可以拥有多个单独的策略并将它们与授权标签堆叠在一起,或者您可以使用一个处理程序来处理多个策略,或者在一个策略中您可以在 policyBuilder(我喜欢这种方法用于很多用例)。请参阅下面的信息和微软链接

注册自定义策略的示例:

Startup.cs

 services.AddAuthorization(authorizationOptions =>
 
    authorizationOptions.AddPolicy(
    "MustBeBornInSummer",
    policyBuilder =>
    
       //add any other policy requirements here too including ones by default
       //eg policyBuilder.RequireAuthenticatedUser();
        policyBuilder.AddRequirements(
            new MustBeBornInSummerRequirement()
            //, new AnotherRequirement()
            );
    );
    //only if you want to register as the default policy
    authorizationOptions.DefaultPolicy = authorizationOptions.GetPolicy("MustBeBornInSummer");
);

然后在授权中

你使用的标签

[Authorize("MustBeBornInSummer")]

您可以设置默认策略,允许您正常使用授权标签

authorizationOptions.DefaultPolicy = authorizationOptions.GetPolicy("MustBeBornInSummer");

您的需求类别

public class MustBeBornInSummerRequirement : IAuthorizationRequirement
    
        public MustBeBornInSummerRequirement ()
        
        
    

处理程序类

 public class MustBeBornInSummerHandler: AuthorizationHandler<MustBeBornInSummerRequirement>
    

        public MustBeBornInSummerHandler ()
        
            //your dependency injections
        

        protected override Task HandleRequirementAsync(
            AuthorizationHandlerContext context, 
            MustBeBornInSummer requirement)
          
//Get the claim you want
            var subject = context.User.Claims.FirstOrDefault(c => c.Type == "sub")?.Value;

            var dateOfBirth = _useryRepository.GetApplicationUserProfile(subject)?.dob;


           //your logic`check user claims then do stuff, or/and check roles too
            if (!bornInSummer)
            
                context.Fail();
                return Task.CompletedTask;
            


            // has claims
            context.Succeed(requirement);
            return Task.CompletedTask;
        
    

在你的配置服务中你需要注册它:

services.AddScoped<IAuthorizationHandler, MustBeBornInSummerHandler>();

您也可以拥有一个处理多个需求的处理程序

public class PermissionHandler : IAuthorizationHandler

    public Task HandleAsync(AuthorizationHandlerContext context)
    
        var pendingRequirements = context.PendingRequirements.ToList();
        foreach (var requirement in pendingRequirements)
        
          if(requirementMustBeBornInSummer
             //Dostuff continue
          elseIf(requirementIsBlah)
        
    

如何处理索赔由你决定,这是我通常的做法

var subject = context.User.Claims.FirstOrDefault(c => c.Type == "sub")?.Value;

var dateOfBirth = _useryRepository.GetApplicationUserProfile(subject)?.dob;


//My repository
public ApplicationUserProfile GetApplicationUserProfile(string subject)

    return _context.ApplicationUserProfiles.FirstOrDefault(a => a.Subject == subject);

您还可以拥有单独的策略并将它们堆叠起来

[Authorize(Policy = "MustBeBornInSummer")]
[Authorize(Policy = "readRole")]

https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-3.1

至于在 JWT 中存储大量数据,对于特定于应用程序的声明,我通常会创建一个表来存储特定应用中用户的声明。然后我使用令牌的“子”来查找用户拥有的声明。这使您无需返回非常大的令牌。

【讨论】:

我们如何在索赔中添加政策? 我不确定你在问什么?如果是关于在哪里存储声明,我刚刚更新了我的答案 我正在使用 asp.net 身份核心。 智威汤逊如何授权策略或者我对此没有明确的概念 在第一个代码块中,我在启动时注册了策略,如果我没有将其设置为默认策略,那么每当我想要使用该策略时,我都会使用以下 [Authorize(Policy = "MustBeBornInSummer ")]`` 在我的控制器中。您的处理程序决定是否满足政策条件。如果政策条件不满足,您可以通过context.Fail(); return Task.CompletedTask;context.Succeed(requirement); return Task.CompletedTask; 如果条件满足

以上是关于如何使用 Web Api Asp.Net Core 实现基于声明的授权?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Asp.net Core Web Api 中默认使用 Newtonsoft.Json?

如何在 ASP.NET Core Web API 中使用 MassTransit 事件总线?

如何使用 Postman 使用 cookie 身份验证测试 ASP.NET Core Web API?

如何使用 Web Api Asp.Net Core 实现基于声明的授权?

带有 EF Core 更新实体的 ASP.Net 核心 Web Api 如何

如何使用asp .net core web api发送连续的数据流?