FilterProvider condicional para WebAPI
Frecuentes
Visto 2,023 veces
3
Tengo una aplicación ASP.NET MVC/WebAPI/AngularJS en la que quiero implementar la protección CSRF. He encontrado algunas soluciones geniales en esto, pero me falta una pieza del rompecabezas. Quiero poder aplicar automáticamente un AuthorizationAttribute personalizado a los métodos no seguros de la API (POST, PUT, etc.). Espero que alguien pueda ayudar.
En el lado de MVC, estoy usando MVC AntiForgeryToken junto con Proveedor de filtro condicional de Phil Haacked, configurado para aplicar el atributo ValidateAntiForgeryToken a todos los métodos POST. La técnica se explica en esta publicación. El código para ConditionalFilterProvider se muestra a continuación:
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);
}
}
Para WebAPI, estoy usando Mecanismo de protección CSRF de AngularJS, lo empaqueté con algunas clases de ayuda para una fácil implementación en el servidor, y estoy decorando los métodos API con un AuthorizeAttribute personalizado, como se describe aquí.
Todo esto funciona según lo previsto, pero me gustaría ir un paso más allá. Siguiendo el patrón usado para los controladores MVC, quiero crear un ConditionalFilterProvider que se pueda usar con los controladores WebAPI para poder asegurarme de que todos los métodos POST se decoren automáticamente con mi AuthorizeAttribute personalizado.
Sin embargo, aunque intenté crear un ConditionalFilterProvider para WebAPI, no estoy seguro de haberlo hecho bien y no puedo probarlo porque no sé cómo registrarlo. Lo que se me ha ocurrido es:
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);
}
}
Y para registrarlo en Application_Start (esto no funciona):
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
}
1 Respuestas
3
Descubrí cómo registrar un IFilterProvider personalizado para WebAPI, probé la solución y funciona correctamente. El código necesario para dar de alta al proveedor es:
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);
}
Respondido el 03 de diciembre de 13 a las 15:12
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas asp.net-mvc angularjs asp.net-web-api action-filter csrf-protection or haz tu propia pregunta.