如何使用Identity 2.0使用Authorize属性在行动中添加多个策略?

时间:2018-10-03 13:44:29

标签: asp.net-core-2.0 claims-based-identity

  

我的身份是2.1.2,具有asp.net core 2.0,我具有应用程序声明表,该表具有声明类型和声明值   即Assets,Assets Edit,Assets,Assets View,其中声明类型与不同的声明值相同,并且我正在使用声明类型名称创建策略,这对我来说很好,不知道如何在一项操作中添加多个策略。以下代码在启动文件中用于创建策略。

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

请多谢一些光线。

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

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

因此,您可以简单地使用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);
        }
    }
}

答案 2 :(得分:0)

如果您只想应用多个策略,则可以执行以下操作:

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

}