我已经在我的应用程序中实现了对CSRF攻击的缓解,这是我在互联网上的一些博客文章上读到的信息。特别是这些帖子一直是我实现的驱动力
ASP的最佳实践。NET MVC从ASP。NET和Web工具开发人员内容团队
跨站点请求伪造攻击的剖析,来自Phil Haack的博客
ASP中的AntiForgeryToken。NET MVC框架- Html。来自David Hayden博客的AntiForgeryToken和ValidateAntiForgeryToken属性
基本上,这些文章和建议说,为了防止CSRF攻击,任何人都应该实现以下代码:
在接受POST Http谓词的每个操作上添加[ValidateAntiForgeryToken]
(HttpPost)
(ValidateAntiForgeryToken)
SomeAction(SomeModel模型){
}
在向服务器提交数据的表单中添加<%= Html.AntiForgeryToken() %> helper
无论如何,在我的应用程序的某些部分,我做Ajax post与jQuery到服务器没有任何形式。例如,当我让用户点击图像来执行特定操作时就会发生这种情况。
假设我有一个包含活动列表的表。我在表的一列上有一个图像,说“标记活动已完成”,当用户单击该活动时,我正在做Ajax POST如下示例:
$("a.markAsDone").click(function (event) {
event.preventDefault();
$.ajax({
type: "post",
dataType: "html",
url: $(this).attr("rel"),
data: {},
success: function (response) {
// ....
}
});
});
在这些情况下,我如何使用<%= Html.AntiForgeryToken() %> ?我是否应该在Ajax调用的数据参数中包含helper调用?
很抱歉写了这么长时间,非常感谢你的帮助
编辑:
根据jayrdub的回答,我用下面的方式
$("a.markAsDone").click(function (event) {
event.preventDefault();
$.ajax({
type: "post",
dataType: "html",
url: $(this).attr("rel"),
data: {
AddAntiForgeryToken({}),
id: parseInt($(this).attr("title"))
},
success: function (response) {
// ....
}
});
});
我知道还有很多其他的答案,但这篇文章非常简洁,迫使你检查所有的httppost,而不仅仅是其中的一些:
http://richiban.wordpress.com/2013/02/06/validating-net-mvc-4-anti-forgery-tokens-in-ajax-requests/
它使用HTTP报头,而不是试图修改表单集合。
服务器
//make sure to add this to your global action filters
[AttributeUsage(AttributeTargets.Class)]
public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
{
public override void OnAuthorization( AuthorizationContext filterContext )
{
var request = filterContext.HttpContext.Request;
// Only validate POSTs
if (request.HttpMethod == WebRequestMethods.Http.Post)
{
// Ajax POSTs and normal form posts have to be treated differently when it comes
// to validating the AntiForgeryToken
if (request.IsAjaxRequest())
{
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
var cookieValue = antiForgeryCookie != null
? antiForgeryCookie.Value
: null;
AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
}
else
{
new ValidateAntiForgeryTokenAttribute()
.OnAuthorization(filterContext);
}
}
}
}
客户端
var token = $('[name=__RequestVerificationToken]').val();
var headers = {};
headers["__RequestVerificationToken"] = token;
$.ajax({
type: 'POST',
url: '/Home/Ajax',
cache: false,
headers: headers,
contentType: 'application/json; charset=utf-8',
data: { title: "This is my title", contents: "These are my contents" },
success: function () {
...
},
error: function () {
...
}
});
我只是在我当前的项目中实现了这个实际问题。我做的所有ajax- post,需要一个认证用户。
首先,我决定钩我的jquery ajax调用,所以我不重复自己太频繁。这个javascript代码片段确保所有ajax (post)调用都会将我的请求验证令牌添加到请求中。注意:名字__RequestVerificationToken是由. net框架使用的,所以我可以利用标准的Anti-CSRF特性,如下所示。
$(document).ready(function () {
var securityToken = $('[name=__RequestVerificationToken]').val();
$('body').bind('ajaxSend', function (elm, xhr, s) {
if (s.type == 'POST' && typeof securityToken != 'undefined') {
if (s.data.length > 0) {
s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken);
}
else {
s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
}
}
});
});
在你的视图中,你需要令牌对上面的javascript可用,只需使用通用的HTML-Helper。基本上,您可以在任何需要的地方添加此代码。我把它放在if(Request.IsAuthenticated)语句中:
@Html.AntiForgeryToken() // you can provide a string as salt when needed which needs to match the one on the controller
在你的控制器中简单地使用标准的ASP。Net MVC Anti-CSRF机制。我是这样做的(尽管我实际上使用了Salt)。
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public JsonResult SomeMethod(string param)
{
// do something
return Json(true);
}
使用Firebug或类似的工具,你可以很容易地看到你的POST请求现在有一个__RequestVerificationToken参数附加。