Asp.net core 如何使用Web Api Asp.Net核心实现基于声明的授权?

Asp.net core 如何使用Web Api Asp.Net核心实现基于声明的授权?,asp.net-core,asp.net-web-api,jwt,authorization,Asp.net Core,Asp.net Web Api,Jwt,Authorization,我正在使用Web API并在登录时生成JWT令牌。关于用户角色和声明,我有一个非常复杂的要求。一个用户可以有多个角色。角色可以有多个声明,用户可以有特定声明。我正在使用Asp.Net核心标识。一个用户可以在AspNetUserClaims中拥有数据,同一个用户可以拥有不同的角色,而每个角色在AspRoleClaims中拥有声明。我已经使用web api成功实现了基于角色的授权,但是如何在web api中实现基于声明的授权 有一件事我已经实现了,但我并不喜欢,那就是我将所有用户声明(包括角色中的声

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

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


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

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

注册自定义策略的示例如下:

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");
});
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;
        }
    }
然后在

您使用的标签

[Authorize("MustBeBornInSummer")]
您可以设置默认策略,该策略允许您正常使用授权标记

authorizationOptions.DefaultPolicy = authorizationOptions.GetPolicy("MustBeBornInSummer");
您的需求类别

 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");
});
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.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");
});
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;
        }
    }
如何处理索赔由你决定,这是我通常的做法

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")]


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

我们如何在索赔中添加保险单?我不确定您在问什么?如果是关于在何处存储声明,我只是更新了我的回答我使用的是asp.net identity core。JWT如何授权策略,或者可能我对它没有明确的概念在启动时注册策略的第一个代码块中,如果我没有将其设置为默认策略,每当我希望使用该策略时,我都会使用以下[authorize(policy=“MustBeBornInSummer”)]``在我的控制器中。您的处理程序决定是否满足策略条件。您可以通过
context.Fail();
return Task.CompletedTask;
在策略条件不满足或
context.success(要求)时执行此操作;
返回任务。已完成任务;
如果满足条件