如何在ASP.NET MVC 4中默认防止CSRF?

时间:2012-04-01 14:56:16

标签: c# csrf asp.net-mvc-4

有没有办法确保默认情况下ASP.NET MVC 4表单受CSRF保护?

例如,有没有办法让AntiForgeryToken 自动应用于视图和控制器操作中的所有表单?

此问题的背景:Prevent Cross-Site Request Forgery (CSRF) using ASP.NET MVC’s AntiForgeryToken() helperAnatomy of a Cross-site Request Forgery Attack

4 个答案:

答案 0 :(得分:22)

为了增加osoviejo的优秀答案,我最近的blog post on CSRF下面的说明将他的工作与Phil的博客中的信息放在一个全面的答案中。

ASP.NET / MVC为此提供了一种机制:您可以添加到全局FilterProviders对象上的过滤器集合。这允许您定位一些控制器而不是其他控制器,添加所需的安全功能。

首先,我们需要实现一个IFilterProvider。下面,您可以找到Phil Haack的Conditional Filter Provider课程。首先将此类添加到项目中。

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);
    }
}

然后,向Application_Start添加代码,将新ConditionalFilterProvider添加到全局FilterProviders集合,以确保所有POST控制器方法都需要AntiForgeryToken。

IEnumerable<Func<ControllerContext, ActionDescriptor, object>> conditions = 
    new Func<ControllerContext, ActionDescriptor, object>[] {
    // Ensure all POST actions are automatically 
    // decorated with the ValidateAntiForgeryTokenAttribute.

    ( c, a ) => string.Equals( c.HttpContext.Request.HttpMethod, "POST",
    StringComparison.OrdinalIgnoreCase ) ?
    new ValidateAntiForgeryTokenAttribute() : null
};

var provider = new ConditionalFilterProvider(conditions);

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

如果您实现上面的两段代码,您的MVC应用程序应该要求每个 POST的AntiForgeryToken到站点。您可以在Phil Haack的CSRF example web site上试用 - 一旦受到保护,CSRF攻击将抛出System.Web.Mvc.HttpAntiForgeryException而无需添加[ValidateAntiForgeryToken]注释。这排除了一大堆“健忘的程序员”相关漏洞。

答案 1 :(得分:11)

您可以使用过滤器提供程序,条件是每当HttpContext.Request.HttpMethod ==“POST”时都应用过滤器ValidateAntiForgeryTokenAttribute()。

我基本上遵循通用方法described by Phil Haack,并添加了适当的条件:

// Ensure all POST actions are automatically decorated with the ValidateAntiForgeryTokenAttribute.
( c, a ) => string.Equals( c.HttpContext.Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase ) ?
 new ValidateAntiForgeryTokenAttribute() : null

答案 2 :(得分:2)

我使用FXCop编写了两个代码分析规则,一个要求HttpMethod属性应用于所有控制器动作,另一个要求任何具有HttpPost属性的动作也必须具有RequiresAntiForgeryToken属性。

这对我们来说效果很好。编写规则并不是特别困难

答案 3 :(得分:0)

一种方法是修改ASP.NET MVC中创建表单的T4模板,让它们自动插入此代码:

<% using(Html.Form("UserProfile", "SubmitUpdate")) { %>
    <%= Html.AntiForgeryToken() %>
    <!-- rest of form goes here -->
<% } %>

当然,您需要控制器方法的相应属性:

[ValidateAntiForgeryToken]
public ViewResult SubmitUpdate()
{
    // ... etc
}

以这种方式改造应用程序并不困难,除非它非常大。我在MVC中写的最后一个应用程序可能需要几个小时才能进行改造。