【问题标题】:How to add multiple policies in action using Authorize attribute using identity 2.0?如何使用身份 2.0 使用 Authorize 属性添加多个策略?
【发布时间】:2019-03-08 18:27:00
【问题描述】:

我是 asp.net core 2.0 的身份 2.1.2,我有应用程序声明表,其中包含声明类型和声明值 即资产,资产编辑,资产,资产视图,其中声明类型与不同的声明值相同,我正在使用声明类型名称创建策略,这对我来说工作正常,不知道如何在一个操作中添加多个策略。下面的代码在启动文件中用于创建策略。

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

请提前给它遮光。

【问题讨论】:

标签: c# asp.net-core claims-based-identity


【解决方案1】:

对于多个策略,您可以实现自己的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)]
    

【讨论】:

【解决方案2】:

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

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

}

编辑:澄清一下,这是附加的 - 您必须通过两个政策要求。

【讨论】:

  • 我认为值得一提的是,这是否会被解释为 AND 或 OR .. 可能是 AND(来自使用 [Authorize(Role=..)] 的官方文档)?
  • 是的,澄清一下,这是附加的 - 您必须通过两个政策要求。
【解决方案3】:

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

因此您可以使用 AddRequirement 内的 AuthorizationPolicyBuilder 简单地将它们添加到您的策略中

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);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    • 2017-07-27
    • 2021-10-30
    • 2019-08-11
    • 1970-01-01
    相关资源
    最近更新 更多