有没有办法确保默认情况下ASP.NET MVC 4表单受CSRF保护?
例如,有没有办法让AntiForgeryToken 自动应用于视图和控制器操作中的所有表单?
此问题的背景:Prevent Cross-Site Request Forgery (CSRF) using ASP.NET MVC’s AntiForgeryToken() helper和Anatomy of a Cross-site Request Forgery Attack。
答案 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中写的最后一个应用程序可能需要几个小时才能进行改造。