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

喜夏-厌秋 提交于 2021-01-29 08:24:28

问题


I'm attempting to setup a custom policy provider in asp.net core. I need to pass in several custom authorization attributes to the provider but struggling with how to do so.

I have it setup to accept one enum array currently and is working fine. However, I would like to add 2 more enum arrays as additional, optional parameters to the authorization attribute.

Attribute as it is now:

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

Would like for it to work like so:

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

LEMClaimAuthorizeAttribute is:

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
}

Custom Authorization Policy Provider:

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. This IS working for one enum array only.
  2. How do I get it to work with other enum array parameters?
  3. If there is a better way, in general, I'm all ears

Thank you for your help!


回答1:


For Custom Policy Provider, it uses LEMClaimAuthorizeAttribute to build the Policy, and then check the generated policys. For passing multiple parameters to LEMClaimAuthorizeAttribute, you need to pay attention to the process to generate the policy string and extract policys from the policystring.

For a solution, follow steps below:

  • 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());
    }
    }
    
  • Use

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


来源:https://stackoverflow.com/questions/52970354/asp-net-core-pass-several-parameters-to-custom-authorization-policy-provider

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!