如何使用 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 实现基于声明的授权?的主要内容,如果未能解决你的问题,请参考以下文章