【问题标题】:asp.net core - pass several parameters to custom authorization policy providerasp.net core - 将几个参数传递给自定义授权策略提供程序
【发布时间】:2019-03-28 22:46:53
【问题描述】:

我正在尝试在 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. 如果有更好的方法,一般来说,我都在听

感谢您的帮助!

【问题讨论】:

    标签: c# asp.net-core asp.net-identity asp.net-authorization


    【解决方案1】:

    对于Custom Policy Provider,它使用LEMClaimAuthorizeAttribute来构建策略,然后检查生成的策略。对于将多个参数传递给LEMClaimAuthorizeAttribute,您需要注意生成策略字符串并从策略字符串中提取策略的过程。

    对于解决方案,请按照以下步骤操作:

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

    【讨论】:

    • 对于那些稍后阅读本文的人,我对周涛的答案所做的唯一更改是将LEMClaimPolicyProvider 强制转换为枚举数组。像这样:var locations = (ia1 != null) ? ia1.Cast&lt;ELocation&gt;().ToArray() : null;
    • GetPolicyAsync 中的 LEMClaimPolicyProvider 对我来说看起来非常糟糕。没有更清洁的方法吗?
    猜你喜欢
    • 2020-01-21
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多