asp.net 核心 - 将几个参数传递给自定义授权策略提供程序

asp.net core - pass several parameters to custom authorization policy provider

我正在尝试在 asp.net 核心中设置自定义策略提供程序。我需要将几个自定义授权属性传递给提供者,但不知道如何做。

我已将其设置为当前接受一个枚举数组并且工作正常。但是,我想再添加 2 个枚举数组作为授权属性的附加可选参数。

现在的属性:

[LEMClaimAuthorize(new ELocation[] { ELocation.Indy, ELocation.Columbus })]

希望它像这样工作:

[LEMClaimAuthorize(new ELocation[] { ELocation.Indy, ELocation.Columbus },
                                           new EEntity[] { EEntity.JobTool })]

LEMClaimAuthorizeAttribute 是:

public class LEMClaimAuthorizeAttribute : AuthorizeAttribute
{
    const string POLICY_PREFIX = "LEMClaim";

    public ELocation[] Locations
    {
        get
        {
            if (Enum.TryParse(typeof(ELocation[]), Policy.Substring(POLICY_PREFIX.Length), out var locations) )
            {
                return (ELocation[]) locations;
            }

            return default(ELocation[]);
        }
        set
        {
            int[] intVals = Array.ConvertAll(value, val => (int)val);
            string arrayVal = string.Join(",", intVals);

            Policy = $"{POLICY_PREFIX}{arrayVal}";
        }
    }

//remaining code omitted for brevity
}

自定义授权策略提供商:

public class LEMClaimPolicyProvider : IAuthorizationPolicyProvider
{
    const string POLICY_PREFIX = "LEMClaim";
    public DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }

    public LEMClaimPolicyProvider(IOptions<AuthorizationOptions> options)
    {
        FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
    }

    public Task<AuthorizationPolicy> GetDefaultPolicyAsync() => FallbackPolicyProvider.GetDefaultPolicyAsync();

    public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
    {
        if (!policyName.StartsWith(POLICY_PREFIX, StringComparison.OrdinalIgnoreCase))
            return FallbackPolicyProvider.GetPolicyAsync(policyName);

        string val = policyName.Substring(POLICY_PREFIX.Length);

        //CONVERT STRING TO INT[]
        int[] ia = val.Split(',').Select(n => Convert.ToInt32(n)).ToArray();
        ELocation[] locations = (ELocation[])(object)ia;

        var policy = new AuthorizationPolicyBuilder();
        policy.AddRequirements(new LEMClaimRequirement(locations));
        return Task.FromResult(policy.Build());


    }
}
  1. 这仅适用于一个枚举数组。
  2. 如何让它与其他枚举数组参数一起使用?
  3. 如果有更好的方法,总的来说,我洗耳恭听

感谢您的帮助!

对于Custom Policy Provider,它使用LEMClaimAuthorizeAttribute构建策略,然后检查生成的策略。对于向LEMClaimAuthorizeAttribute传递多个参数,需要注意生成policy string和从policystring中提取策略的过程。

如需解决方案,请按照以下步骤操作:

  • LEMClaimAuthorizeAttribute.cs

    public class LEMClaimAuthorizeAttribute : AuthorizeAttribute
    {
    public LEMClaimAuthorizeAttribute(ELocation[] eLocations, EEntity[] eEntities = null)
    //public LEMClaimAuthorizeAttribute(ELocation[] eLocations)
    {
        Locations = eLocations;
        Entitys = eEntities;
    }
    const string POLICY_PREFIX_ELocation = "LEMClaim.ELocation";
    const string POLICY_PREFIX_EEntity = "LEMClaim.EEntity";
    
    public ELocation[] Locations
    {
        get
        {
            if (Enum.TryParse(typeof(ELocation[]), Policy.Substring(POLICY_PREFIX_ELocation.Length), out var locations))
            {
                return (ELocation[])locations;
            }
    
            return default(ELocation[]);
        }
        set
        {
            if (value != null)
            {
                int[] intVals = Array.ConvertAll(value, val => (int)val);
                string arrayVal = string.Join(",", intVals);
    
                Policy = Policy == null ? $"{POLICY_PREFIX_ELocation}{arrayVal}" : Policy + $";{POLICY_PREFIX_ELocation}{arrayVal}";
            }
    
        }
    }
    public EEntity[] Entitys
    {
        get
        {
            if (Enum.TryParse(typeof(EEntity[]), Policy.Substring(POLICY_PREFIX_EEntity.Length), out var locations))
            {
                return (EEntity[])locations;
            }
    
            return default(EEntity[]);
        }
        set
        {
            if (value != null)
            {
                int[] intVals = Array.ConvertAll(value, val => (int)val);
                string arrayVal = string.Join(",", intVals);
                Policy = Policy == null ? $"{POLICY_PREFIX_EEntity}{arrayVal}" : Policy + $";{POLICY_PREFIX_EEntity}{arrayVal}";
            }
        }
    }
    
    //remaining code omitted for brevity
     }
    
  • LEMClaimRequirement.cs

    public class LEMClaimRequirement : IAuthorizationRequirement
    {
    public LEMClaimRequirement(ELocation[] eLocations, EEntity[] eEntities = null)
    {
        Locations = eLocations;
        Entitys = eEntities;
    }
    public ELocation[] Locations
    {
        get; set;
    }
    public EEntity[] Entitys
    {
        get; set;
    }
    }
    
  • LEMClaimPolicyProvider.cs

    public class LEMClaimPolicyProvider : IAuthorizationPolicyProvider
    {
    const string POLICY_PREFIX = "LEMClaim";
    const string POLICY_PREFIX_ELocation = "LEMClaim.ELocation";
    const string POLICY_PREFIX_EEntity = "LEMClaim.EEntity";
    
    public DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }
    
    public LEMClaimPolicyProvider(IOptions<AuthorizationOptions> options)
    {
        FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
    }
    
    public Task<AuthorizationPolicy> GetDefaultPolicyAsync() => FallbackPolicyProvider.GetDefaultPolicyAsync();
    
    public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
    {
        if (!policyName.StartsWith(POLICY_PREFIX, StringComparison.OrdinalIgnoreCase))
            return FallbackPolicyProvider.GetPolicyAsync(policyName);
        var val = policyName.Split(";");
        //get locations
        int[] ia1 = val.FirstOrDefault(k => k.StartsWith(POLICY_PREFIX_ELocation, StringComparison.OrdinalIgnoreCase))
                       .Substring(POLICY_PREFIX_ELocation.Length)
                       .Split(',').Select(n => Convert.ToInt32(n)).ToArray();
        ELocation[] locations = (ELocation[])(object)ia1;
        int[] ia2 = val.FirstOrDefault(k => k.StartsWith(POLICY_PREFIX_EEntity, StringComparison.OrdinalIgnoreCase))
                       ?.Substring(POLICY_PREFIX_EEntity.Length)
                       ?.Split(',').Select(n => Convert.ToInt32(n)).ToArray();
        EEntity[] entitys = (EEntity[])(object)ia2;
    
        var policy = new AuthorizationPolicyBuilder();
        policy.AddRequirements(new LEMClaimRequirement(locations, entitys));
        return Task.FromResult(policy.Build());
    }
    }
    
  • 使用

        [LEMClaimAuthorize(new ELocation[] { ELocation.Indy, ELocation.Columbus })]
    public ActionResult One()
    {
        return View();
    }
    [LEMClaimAuthorize(new ELocation[] { ELocation.Indy, ELocation.Columbus }, new EEntity[] { EEntity.JobTool })]
    public ActionResult Two()
    {
        return View();
    }