繁体   English   中英

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

[英]How to implement Claim based authorization using Web Api Asp.Net Core?

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

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

或者在 Web API Dot Net core 中进行基于声明的授权的另一种方法是什么?

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

注册自定义策略的示例:

启动.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")]

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

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

您的要求 class

public class MustBeBornInSummerRequirement : IAuthorizationRequirement
    {
        public MustBeBornInSummerRequirement ()
        {
        }
    }

处理器 class

 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 中存储大量数据,对于特定于应用程序的声明,我通常会创建一个表来存储特定应用程序中用户的声明。 然后我使用令牌的“子”来查找用户拥有的声明。 这使您不再需要返回非常大的令牌。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM