Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automating Anti Forgery Token Validation on MVC Apps

Is there a way to automatically have [ValidateAntiForgeryToken] annotation on all HTTP post methods on a controller without having to explicitly defining it?

and also is there a way to extend the MVC Html.BeginForm() helper to include the anti forgery token at all times?

and finally the purpose of doing this is to keep things consistent across the application, can there be a reason not to do this for some scenarios?

like image 509
Ahsan Avatar asked Jun 02 '15 01:06

Ahsan


1 Answers

I was researching this topic myself and compiled full solution below and also here. It consists of few parts including AntiForgeryTokenFilterProvider and BeginSecureForm helper method. It also allows to skip validation for a single action with DisableAntiForgeryCheckAttribute.

public class AntiForgeryTokenFilterProvider : IFilterProvider
{
    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        IEnumerable<FilterAttribute> filters = actionDescriptor.GetFilterAttributes(true);

        bool disableAntiForgery = filters.Any(f => f is DisableAntiForgeryCheckAttribute);

        string method = controllerContext.HttpContext.Request.HttpMethod;

        if (!disableAntiForgery
            && String.Equals(method, "POST", StringComparison.OrdinalIgnoreCase))
        {
            yield return new Filter(new ValidateAntiForgeryTokenAttribute(), FilterScope.Global, null);
        }
    }
}

[AttributeUsage(AttributeTargets.Method)]
public sealed class DisableAntiForgeryCheckAttribute : FilterAttribute
{
}

// Usage:
public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //**//
        FilterProviders.Providers.Add(new AntiForgeryTokenFilterProvider());
        //**//
    }
}

// Html Helper method
public static class HtmlExtensions
{
    public static MvcForm BeginSecureForm(this HtmlHelper html, string action, string controller)
    {
        var form = html.BeginForm(action, controller);
        html.ViewContext.Writer.Write(html.AntiForgeryToken().ToHtmlString());

        return form;
    }
}
like image 86
Vadim K. Avatar answered Oct 18 '22 20:10

Vadim K.