如何使用身份 2.0 使用授权属性添加多个策略?

How to add multiple policies in action using Authorize attribute using identity 2.0?

我是 asp.net 核心 2.0 的身份 2.1.2,我有申请声明 table,它有声明类型和声明价值 即资产、资产编辑、资产、资产视图,其中声明类型与不同的声明值相同,我正在使用声明类型名称创建策略,这对我来说工作正常不知道如何在一个操作中添加多个策略。以下代码在启动文件中用于创建策略。

services.AddAuthorization(options =>
{
   var dbContext = SqlServerDbContextOptionsExtensions.UseSqlServer(new DbContextOptionsBuilder<MyDBContext>(),
      Configuration.GetConnectionString("TestIdentityClaimAuth")).Options;

   var dbCon = new MyDBContext(dbContext);
   //Getting the list of application claims.
   var applicationClaims = dbCon.ApplicationClaims.ToList();
   var strClaimValues = string.Empty;
   List<ClaimVM> lstClaimTypeVM = new List<ClaimVM>();
   IEnumerable<string> lstClaimValueVM = null;// new IEnumerable<string>();

   lstClaimTypeVM = (from dbAppClaim
         in dbCon.ApplicationClaims
      select new ClaimVM
      {
         ClaimType = dbAppClaim.ClaimType
      }).Distinct().ToList();

   foreach (ClaimVM objClaimType in lstClaimTypeVM)
   {
      lstClaimValueVM = (from dbClaimValues in dbCon.ApplicationClaims
         where dbClaimValues.ClaimType == objClaimType.ClaimType
         select dbClaimValues.ClaimValue).ToList();

      options.AddPolicy(objClaimType.ClaimType, policy => policy.RequireClaim(objClaimType.ClaimType, lstClaimValueVM));
      lstClaimValueVM = null;
   }
});

并且在我的控制器中使用这样的 Autherize 属性。

[Authorize(Policy = "Assets Edit")]

请提前给它遮光。

对于多个策略,您可以实施自己的 AuthorizeAttribute

  • MultiplePolicysAuthorizeAttribute

    public class MultiplePolicysAuthorizeAttribute : TypeFilterAttribute
    {
         public MultiplePolicysAuthorizeAttribute(string policys, bool isAnd = false) : base(typeof(MultiplePolicysAuthorizeFilter))
         {
             Arguments = new object[] { policys, isAnd };
         }
    }
    
  • MultiplePolicysAuthorizeFilter

    public class MultiplePolicysAuthorizeFilter : IAsyncAuthorizationFilter
    {
        private readonly IAuthorizationService _authorization;
        public string Policys { get; private set; }
        public bool IsAnd { get; private set; }
    
        public MultiplePolicysAuthorizeFilter(string policys, bool isAnd, IAuthorizationService authorization)
        {
           Policys = policys;
           IsAnd = isAnd;
           _authorization = authorization;
        }
    
        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            var policys = Policys.Split(";").ToList();
            if (IsAnd)
            {
                foreach (var policy in policys)
                {
                    var authorized = await _authorization.AuthorizeAsync(context.HttpContext.User, policy);
                    if (!authorized.Succeeded)
                    {
                        context.Result = new ForbidResult();
                        return;
                    }
    
                }
             }
             else
             {
                foreach (var policy in policys)
                {
                     var authorized = await _authorization.AuthorizeAsync(context.HttpContext.User, policy);
                     if (authorized.Succeeded)
                     {
                         return;
                     }
    
                }
                context.Result = new ForbidResult();
                return;
            }
         }
    }
    
  • 只需要其中一项保单

    [MultiplePolicysAuthorize("Assets View;Assets Edit;Assets Delete")]
    
  • 只需要所有政策

    [MultiplePolicysAuthorize("Assets View;Assets Edit;Assets Delete", true)]
    

如果您只想应用多个策略,您可以这样做:

[Authorize(Policy = "Asset")]
[Authorize(Policy = "Edit")]
public class MyController : Controller {

}

编辑:澄清一下,这是附加的 - 您必须满足这两项政策要求。

您可以使用 make multiple requirements class 实现 IAuthorizationRequirement,并将 AuthorizationHandler 的多个需求处理程序注册到 DI 容器。

因此您只需使用 AuthorizationPolicyBuilder

中的 AddRequirement 将它们添加到您的政策中
public AuthorizationPolicyBuilder AddRequirements(params IAuthorizationRequirement[] requirements);

Startup.cs:

services.AddScoped<IAuthorizationHandler, FooHandler>();
services.AddScoped<IAuthorizationHandler, BooHandler>();

services.AddAuthorization(authorizationOptions =>
{
    authorizationOptions.AddPolicy(
        "FooAndBooPolicy",
        policyBuilder =>
        {
            policyBuilder.RequireAuthenticatedUser();
            policyBuilder.AddRequirements(new FooRequirement(), new BooRequirement());
        });
});

Requirements.cs:

public class FooRequirement : IAuthorizationRequirement { }    
public class FooHandler : AuthorizationHandler<FooRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationContext context, FooRequirement requirement)
    {
        if (context.User.HasClaim(c => c.Type == "Foo" && c.Value == true))
        {
            context.Succeed(requirement);
            return Task.FromResult(0);
        }
    }
}

public class BooRequirement : IAuthorizationRequirement { }    
public class BooHandler : AuthorizationHandler<BooRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationContext context, BooRequirement requirement)
    {
        if (context.User.HasClaim(c => c.Type == "Boo" && c.Value == true))
        {
            context.Succeed(requirement);
            return Task.FromResult(0);
        }
    }
}