Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
321 views
in Technique[技术] by (71.8m points)

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

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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...