【问题标题】:How to implement Claim based authorization using Web Api Asp.Net Core?如何使用 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 核心中进行基于声明的授权的其他方法是什么?

【问题讨论】:

    标签: asp.net-core asp.net-web-api jwt authorization


    【解决方案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; 如果条件满足
    猜你喜欢
    • 1970-01-01
    • 2017-06-08
    • 2018-12-28
    • 1970-01-01
    • 2021-04-26
    • 2014-03-15
    • 1970-01-01
    • 2012-11-07
    相关资源
    最近更新 更多