【问题标题】:On Asp.net Web Api authorization filters, how can I access to parameters?在 Asp.net Web Api 授权过滤器上,如何访问参数?
【发布时间】:2013-04-09 20:14:01
【问题描述】:

我从 Asp.Net Web API 开始,这是我的问题:

我实现了一个自定义授权过滤器来检查我的消息头以查找 API 密钥。基于此 API 密钥,我检索了我的用户,然后我想看看他是否可以访问某些资源。我要检查的资源 ID 在 HTTP 请求的参数上。但是当我使用 AuthorizationFilter 方法时,操作参数列表是空的。

我该怎么做?

如果我使用 ActionFilter 代替授权过滤器,我如何确定这将是第一个执行的过滤器?在全局范围内,如何指定过滤器的执行顺序?

最后一个问题,是否可以在“管道上”添加一些我可以在任何过滤器上检索的数据?类似于会话存储但仅限于请求的东西?

感谢您的回复

【问题讨论】:

    标签: asp.net-web-api authorization


    【解决方案1】:

    获取参数的另一种方法是Execute 参数的绑定。

    try
    {
        var binding = actionContext.ActionDescriptor.ActionBinding;
        var parameters = binding.ParameterBindings.OfType<ModelBinderParameterBinding>();
        var newBinding = new HttpActionBinding(actionContext.ActionDescriptor, parameters.ToArray());
        newBinding.ExecuteBindingAsync(actionContext, new CancellationToken());
        var id = actionContext.ActionArguments["id"] as string;
    }
    catch
    {
        base.HandleUnauthorizedRequest(actionContext);
    }
    

    注意:您需要确保只过滤来自请求 URI 的参数,因为我注意到对预期来自请求的任何参数执行绑定body 将不再传递给实际操作。即这些参数将为 null

    这只是为了说明您可以这样做,我建议使用GetRouteData()/RouteData,因为它不太可能破坏 ASP.NET MVC 模型绑定的进一步流程。

    var routeData = actionContext.ControllerContext.RouteData;
    var id = routeData.Values["id"] as string;
    

    【讨论】:

      【解决方案2】:

      授权属性在参数绑定运行之前运行,因此您不能(如您所见)使用ActionArguments 集合。相反,您需要将请求 uri 用于查询参数,并将路由数据用于 uri 参数,如下所示。

      //request at http://localhost/api/foo/id?MyValue=1
      public class MyAuthorizationAttribute : AuthorizeAttribute
      {
          protected override bool IsAuthorized(HttpActionContext actionContext)
          {
              //will not work as parameter binding has not yet run
              object value;
              actionContext.ActionArguments.TryGetValue("id", out value);
      
              //Will get you the resource id assuming a default route like /api/foo/{id} 
              var routeData = actionContext.Request.GetRouteData();
              var myId = routeData.Values["id"] as string;
      
              //uri is still accessible so use this to get query params
              var queryString = HttpUtility.ParseQueryString(actionContext.Request.RequestUri.Query);
              var myQueryParam = queryString["MyValue"];
      
              //and so on
          }
      }
      

      关于执行顺序

      使用FilterScope Enumeration...范围指定过滤器的执行顺序有 3 种不同的方式,分别是全局、控制器和操作。 AuthoriseAttribute 是“全球”,因此它

      在 Controller 之前指定一个动作。

      如果您需要在这 3 个范围内指定执行顺序,那么您应该阅读 this blog article 此处您需要实现 FilterProvider

      向管道添加一些数据

      对请求使用属性集合,此集合在请求期间可用。

          protected override bool IsAuthorized(HttpActionContext actionContext)
          {
              actionContext.Request.Properties.Add("__MYKEY__","MyValue");
      
              //access this later in the controller or other action filters using
              var value = actionContext.Request.Properties["__MYKEY__"];
      
          }
      

      【讨论】:

      • 还可以从RouteData中获取路径参数信息。如果记忆对我有用,它会类似于 Request.GetRouteData().Values;
      • @DarrelMiller,我刚刚跟进了这个想法,但我的安全带似乎并没有那样工作。 var routeData = actionContext.Request.GetRouteData(); var value = routeData.Values["MyValue"] 作为字符串;我的 routeData 仅包含控制器值。如果您不同意,请告诉我,我会进一步调查。
      • 首先使用授权过滤器将值设置为请求属性,然后操作过滤器开始工作。其他信息也很有用。感谢您的帮助。
      • @MarkJones 我刚刚尝试使用默认的/api/values/{id} 路由,我能够在 AuthorizeAttribute 的 OnAuthorization 事件中从 RouteData 读取Id
      • @DarrelMiller 我认为这个问题是指查询字符串参数。同意 ID 将按照您的建议可用。
      猜你喜欢
      • 2014-07-18
      • 1970-01-01
      • 2016-08-02
      • 2021-07-22
      • 2011-03-28
      • 1970-01-01
      • 2021-10-07
      • 1970-01-01
      • 2012-09-30
      相关资源
      最近更新 更多