我已经在我的应用程序中实现了对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) {
// ....
}
});
});
1.定义函数从服务器获取令牌
@function
{
public string TokenHeaderValue()
{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
}
}
2.在发送到服务器之前获取令牌并设置报头
var token = '@TokenHeaderValue()';
$http({
method: "POST",
url: './MainBackend/MessageDelete',
data: dataSend,
headers: {
'RequestVerificationToken': token
}
}).success(function (data) {
alert(data)
});
3.Onserver验证HttpRequestBase的方法你处理Post/get
string cookieToken = "";
string formToken = "";
string[] tokens = Request.Headers["RequestVerificationToken"].Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
AntiForgery.Validate(cookieToken, formToken);
我知道还有很多其他的答案,但这篇文章非常简洁,迫使你检查所有的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 () {
...
}
});