Search code examples
c#asp.net-mvcasp.net-mvc-3csrfglobal-asax

Anti-CSRF implementation in MVC 3


I would like to implement Anti-CSRF token in Global.asax file of MVC 3. Is that possible to implement the same in Gloabl.asax file.


Solution

  • Seems what you need is to create a custom filter class which implements IAuthorizationFilter for all POST methods, by checking HttpContext.Request.HttpMethod request:

    public class ValidateAntiForgeryTokenEveryPost : IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext context)
        {
            if (context.HttpContext.Request.HttpMethod == "POST")
            {
                System.Web.Helpers.AntiForgery.Validate();
            }
        }
    }
    

    Then, add the new filter in FilterConfig class:

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new ValidateAntiForgeryTokenEveryPost());
        }
    }
    

    Also ensure that the custom filter has registered in Global.asax code:

    protected void Application_Start()
    {
        // other settings
    
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    
        // other settings
    }
    

    By using global filtering given above, all POST method requests are automatically checks for AntiForgeryToken, no matter if @Html.AntiForgeryToken() is not present inside view pages.

    Addendum 1:

    It is possible to exclude certain actions from CSRF token checking, what you need is preventing Validate method to execute while a custom attribute class is present. First, create a custom attribute class for validation check:

    [AttributeUsage(AttributeTargets.Method)]
    public class ExcludeAntiForgeryCheckAttribute : Attribute
    {
        // other stuff
    }
    

    Afterwards, use ActionDescriptor.GetCustomAttributes to get custom attribute type created above:

    public class ValidateAntiForgeryTokenEveryPost : IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext context)
        {
            // adapted from Darin Dimitrov (/a/34588606/)
            bool isValidate = !context.ActionDescriptor.GetCustomAttributes(typeof(ExcludeAntiForgeryCheckAttribute), true).Any();
    
            // use AND operator (&&) if you want to exclude POST requests marked with custom attribute
            // otherwise, use OR operator (||)
            if (context.HttpContext.Request.HttpMethod == "POST" && isValidate)
            {
                System.Web.Helpers.AntiForgery.Validate();
            }
        }
    }
    

    Then you can decorate any methods which should be exempted from CSRF validation token:

    [HttpPost]
    [ExcludeAntiForgeryCheck]
    public ActionResult Index(ViewModel model)
    {
        // other stuff
    
        return View(model);
    }
    

    References:

    Check CRSF token by default in ASP.NET MVC (standard version)

    Securing all forms using AntiForgeryToken (attribute-based version)