【问题标题】:Conditional FilterProvider for WebAPIWebAPI 的条件 FilterProvider
【发布时间】:2013-12-19 12:55:51
【问题描述】:

我有一个 ASP.NET MVC / WebAPI / AngularJS 应用程序,我想在其中实现 CSRF 保护。我已经找到了一些很好的解决方案,但我错过了一个难题。我希望能够自动将自定义 AuthorizationAttribute 应用于 API 非安全方法(POST、PUT 等)。我希望有人可以提供帮助。

在 MVC 方面,我将 MVC AntiForgeryToken 与 Phil Haacked's ConditionalFilterProvider 结合使用,配置为将 ValidateAntiForgeryToken 属性应用于所有 POST 方法。该技术在this post 中进行了解释。 ConditionalFilterProvider 的代码如下:

using System.Web.Mvc;

public class ConditionalFilterProvider : IFilterProvider
{
    private readonly
      IEnumerable<Func<ControllerContext, ActionDescriptor, object>> _conditions;

    public ConditionalFilterProvider(
      IEnumerable<Func<ControllerContext, ActionDescriptor, object>> conditions)
    {
        _conditions = conditions;
    }

    public IEnumerable<Filter> GetFilters(
        ControllerContext controllerContext,
        ActionDescriptor actionDescriptor)
    {
        return from condition in _conditions
               select condition(controllerContext, actionDescriptor) into filter
               where filter != null
               select new Filter(filter, FilterScope.Global, null);
    }
}

对于 WebAPI,我使用 AngularJS's CSRF protection mechanism,将其与一些帮助类打包在一起以便在服务器上轻松实现,并且我使用自定义 AuthorizeAttribute 装饰 API 方法,如 here 所述。

所有这些都按预期工作,但我想更进一步。按照用于 MVC 控制器的模式,我想创建一个可与 WebAPI 控制器一起使用的 ConditionalFilterProvider,以便我可以确保所有 POST 方法都使用我的自定义 AuthorizeAttribute 自动修饰。

但是,尽管我尝试为 WebAPI 创建 ConditionalFilterProvider,但我不确定我是否正确,也无法测试它,因为我不知道如何注册它。我想出的是:

using System.Web.Http;

public class ConditionalApiFilterProvider : IFilterProvider
{
    private readonly
      IEnumerable<Func<HttpConfiguration, HttpActionDescriptor, object>> _conditions;

    public ConditionalApiFilterProvider(
      IEnumerable<Func<HttpConfiguration, HttpActionDescriptor, object>> conditions)
    {
        _conditions = conditions;
    }

    public IEnumerable<FilterInfo> GetFilters(
        HttpConfiguration configuration,
        HttpActionDescriptor actionDescriptor)
    {
        return from condition in _conditions
               select condition(configuration, actionDescriptor) into filter
               where filter != null
               select new FilterInfo(filter as IFilter, FilterScope.Action);
    }
}

并在 Application_Start 中注册它(这不起作用):

    private void ConfigureValidateCsrfHeaderAttribute()
    {
        //Configure a conditional filter
        string[] nonSafeMethods = { "post", "put", "delete" };
        IEnumerable<Func<HttpConfiguration, HttpActionDescriptor, object>> conditions =
            new Func<HttpConfiguration, HttpActionDescriptor, object>[] {
                    ( c, a ) => nonSafeMethods.Contains("need HTTP method here") ?
                    new ValidateCsrfHeaderAttribute() : null
            };

        var provider = new ConditionalApiFilterProvider(conditions);

        // This line adds the filter we created above
        FilterProviders.Providers.Add(provider);        //incorrect provider registration
    }

【问题讨论】:

    标签: asp.net-mvc angularjs asp.net-web-api action-filter csrf-protection


    【解决方案1】:

    发现了如何为 WebAPI 注册一个自定义 IFilterProvider,测试了解决方案并且它可以正常工作。注册提供者所需的代码是:

    using System.Web.Http;
    using System.Web.Http.Filters;
    
    private void ConfigureValidateCsrfHeaderAttribute()
    {
        //Configure a conditional filter
        HttpMethod[] nonSafeMethods = { HttpMethod.Post, HttpMethod.Put, HttpMethod.Delete };
        IEnumerable<Func<HttpConfiguration, HttpActionDescriptor, object>> conditions =
            new Func<HttpConfiguration, HttpActionDescriptor, object>[] {
                    ( c, a ) => nonSafeMethods.Any(m => a.SupportedHttpMethods.Contains(m)) ?
                    new ValidateCsrfHeaderAttribute() : null
        };
    
        var provider = new ConditionalApiFilterProvider(conditions);
    
        // This line adds the filter we created above
        GlobalConfiguration.Configuration.Services.Add(typeof(IFilterProvider), provider);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-23
      • 2022-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多