【问题标题】:CSRF Protection in AJAX Requests using MVC2使用 MVC2 的 AJAX 请求中的 CSRF 保护
【发布时间】:2011-01-21 22:45:28
【问题描述】:

我正在构建的页面很大程度上依赖于 AJAX。基本上,只有一个“页面”,每个数据传输都通过 AJAX 处理。由于浏览器端过度乐观的缓存会导致奇怪的问题(数据未重新加载),我必须使用 POST 执行所有请求(也读取) - 这会强制重新加载。

现在我想阻止页面针对 CSRF。通过表单提交,使用Html.AntiForgeryToken() 可以很好地工作,但是在 AJAX 请求中,我想我必须手动附加令牌?有什么开箱即用的东西吗?

我目前的尝试是这样的

我很想重用现有的魔法。但是,HtmlHelper.GetAntiForgeryTokenAndSetCookie 是私有的,我不想在 MVC 中乱搞。另一种选择是编写一个扩展,如

public static string PlainAntiForgeryToken(this HtmlHelper helper)
{
    // extract the actual field value from the hidden input
    return helper.AntiForgeryToken().DoSomeHackyStringActions();
}

这有点 hacky 并留下更大的问题未解决:如何验证该令牌?默认验证实现是内部的,并且针对使用表单字段进行了硬编码。我试着写了一个稍微修改过的ValidateAntiForgeryTokenAttribute,但它使用了一个私有的AntiForgeryDataSerializer,我也真的不想复制它。

在这一点上,提出一个本土解决方案似乎更容易,但这确实是重复代码。

任何建议如何以聪明的方式做到这一点?我是否遗漏了一些非常明显的东西?

【问题讨论】:

    标签: asp.net ajax security asp.net-mvc-2 csrf


    【解决方案1】:

    您可以使用传统的 Html.AntiForgeryToken() 帮助器在页面某处(不一定在表单内)生成隐藏字段,并将其包含在 ajax 请求中:

    var token = $('input[name=__RequestVerificationToken]').val();
    $.post(
        '/SomeAction', { '__RequestVerificationToken': token }, 
        function() {
            alert('Account Deleted.');
        }
    );
    

    在服务器端进行验证:

    [AcceptVerbs(HttpVerbs.Post)]
    [ValidateAntiForgeryToken]
    public ActionResult SomeAction() 
    {
        return View();
    }
    

    如果您的页面上有多个标记,您可能需要指定要包含的标记。由于现有的 helper 生成了具有相同名称的隐藏字段,因此很难制作一个好的选择器,因此您可以将它们放在 span 中:

    <span id="t1"><%= Html.AntiForgeryToken() %></span>
    <span id="t2"><%= Html.AntiForgeryToken() %></span>
    

    然后选择对应的token:

    var token = $('#t1 input[name=__RequestVerificationToken]').val();
    

    【讨论】:

    • 太棒了!奇迹般有效!我不知道发布的字段最终会出现在Request.Form 中。 +1 非常简洁的选择语句。干杯!
    猜你喜欢
    • 2019-01-25
    • 2017-09-01
    • 2015-10-15
    • 2015-10-06
    • 2022-10-17
    • 2014-02-19
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多