我有一个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
}
答案 0 :(得分:3)
发现了如何为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);
}