我已经在我的应用程序中实现了对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) {
            // ....
        }
    });
});

当前回答

这是我见过的最简单的方法。注意:确保在视图中有“@Html.AntiForgeryToken()”

  $("a.markAsDone").click(function (event) {
        event.preventDefault();
        var sToken = document.getElementsByName("__RequestVerificationToken")[0].value;
        $.ajax({
            url: $(this).attr("rel"),
            type: "POST",
            contentType: "application/x-www-form-urlencoded",
            data: { '__RequestVerificationToken': sToken, 'id': parseInt($(this).attr("title")) }
        })
        .done(function (data) {
            //Process MVC Data here
        })
        .fail(function (jqXHR, textStatus, errorThrown) {
            //Process Failure here
        });
    });

其他回答

function DeletePersonel(id) {

    var data = new FormData();
    data.append("__RequestVerificationToken", "@HtmlHelper.GetAntiForgeryToken()");

    $.ajax({
        type: 'POST',
        url: '/Personel/Delete/' + id,
        data: data,
        cache: false,
        processData: false,
        contentType: false,
        success: function (result) {
        }
    });
}

public static class HtmlHelper {
    public static string GetAntiForgeryToken() {
        System.Text.RegularExpressions.Match value = 
                System.Text.RegularExpressions.Regex.Match(System.Web.Helpers.AntiForgery.GetHtml().ToString(), 
                        "(?:value=\")(.*)(?:\")");
        if (value.Success) {
            return value.Groups[1].Value;
        }
        return "";
    }
}

我喜欢360Airwalk提供的解决方案,但它可能会有所改进。

第一个问题是,如果使用空数据创建$.post(), jQuery不会添加Content-Type标头。NET MVC无法接收和检查令牌。所以你必须确保页眉一直在那里。

另一个改进是支持所有带有内容的HTTP动词:POST、PUT、DELETE等。虽然可以在应用程序中只使用post,但最好有一个通用的解决方案,并验证使用任何谓词接收的所有数据都具有防伪造令牌。

$(document).ready(function () {
    var securityToken = $('[name=__RequestVerificationToken]').val();
    $(document).ajaxSend(function (event, request, opt) {
        if (opt.hasContent && securityToken) {   // handle all verbs with content
            var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
            opt.data = opt.data ? [opt.data, tokenParam].join("&") : tokenParam;
            // ensure Content-Type header is present!
            if (opt.contentType !== false || event.contentType) {
                request.setRequestHeader( "Content-Type", opt.contentType);
            }
        }
    });
});

好吧,这里有很多帖子,没有一个对我有帮助,一天又一天的谷歌,仍然没有进一步的我得到的点wr-从头开始编写整个应用程序,然后我注意到这个小块在我的web .conf

 <httpCookies requireSSL="false" domain="*.localLookup.net"/>

现在我不知道为什么我添加了它,但我已经注意到,它在调试模式下被忽略,而不是在生产模式下(IE安装到IIS某处)

对我来说,解决方案是2个选项之一,因为我不记得我为什么添加它,我不能确定其他事情不依赖于它,第二域名必须全部小写,TLD不像我在*.localLookup.net中做的那样

也许有用,也许没有。我希望它能帮助到一些人

这是我见过的最简单的方法。注意:确保在视图中有“@Html.AntiForgeryToken()”

  $("a.markAsDone").click(function (event) {
        event.preventDefault();
        var sToken = document.getElementsByName("__RequestVerificationToken")[0].value;
        $.ajax({
            url: $(this).attr("rel"),
            type: "POST",
            contentType: "application/x-www-form-urlencoded",
            data: { '__RequestVerificationToken': sToken, 'id': parseInt($(this).attr("title")) }
        })
        .done(function (data) {
            //Process MVC Data here
        })
        .fail(function (jqXHR, textStatus, errorThrown) {
            //Process Failure here
        });
    });

我认为你所要做的就是确保“__RequestVerificationToken”输入包含在POST请求中。另一半信息(即用户cookie中的令牌)已经通过AJAX POST请求自动发送。

例如,

$("a.markAsDone").click(function (event) {
    event.preventDefault();
    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: { 
            "__RequestVerificationToken":
            $("input[name=__RequestVerificationToken]").val() 
        },
        success: function (response) {
            // ....
        }
    });
});