Django 1.3 中的 Ajax CSRF 问题

Posted

技术标签:

【中文标题】Django 1.3 中的 Ajax CSRF 问题【英文标题】:Ajax CSRF problem in Django 1.3 【发布时间】:2011-07-26 20:32:33 【问题描述】:

根据 django 文档,对于 1.3 中的 ajax 发布请求(至少使用 Jquery),我们只需将这个 snippet 添加到主 js 文件中。这个 sn -p 从 cookie 中获取 csrftoken,然后为所有 ajax 请求设置它。这是可行的,但是如果 cookie 中不存在 csrftoken 怎么办?我认为 render_to_response 和 render 都会自动检查会话中的 csrftoken 是否存在,并为我们设置它,如果令牌不存在。但他们不是。那么,我需要自己实现它吗?或者也许有另一种方法来处理 ajax csrf 保护?

【问题讨论】:

【参考方案1】:

当已经使用 % csrf_token % 的页面上没有表单时,不会发送 cookie。因此,正如您所指出的,当您尝试在此类页面上使用 Ajax 时,您将收到错误消息。如果您的网站包含各种页面以及各种表单和 ajax 帖子组合,这将导致行为不稳定。

此问题已报告并修复:https://code.djangoproject.com/ticket/15354

补丁中的解决方案,将在 1.3.1 中推出,是 ensure_cookie_csrf 装饰器。该装饰器在 1.3 或 1.2.5 中不存在

不过,无需等待。只需将此行添加到任何包含 AJAX 的视图中即可发布 CSRF 表单:

request.META["CSRF_COOKIE_USED"] = True

例子:

def calculator(request):
    request.META["CSRF_COOKIE_USED"] = True
    return render_to_response('calc.html', 'form': CalcForm())

仅供参考 - 这正是装饰器所做的。

【讨论】:

根据CSRF Django documentation,ensure_cookie_csrf 装饰器是 Django 1.4 的新特性。 是的,ensure_csrf_cookie 装饰器登陆 Django 1.4。不幸的是 1.3.1 中没有【参考方案2】:

如果在模板中使用模板标签% csrf_token % 来生成请求,或者如果您从@987654324 调用get_token(使用request 对象作为参数),您的cookie 将只包含CSRF 令牌@。

get_token 函数在request 对象上设置元信息,然后告诉django.middleware.csrf.CsrfViewMiddleware 中间件设置cookie。

【讨论】:

【参考方案3】:

对于 Ajax,您应该在每个请求中传递 csrf 令牌。对于 jQuery,我使用以下代码:

$.ajaxPrefilter(function(options, originalOptions, jqXHR) 
    if(!options.crossDomain) 
        if(options.data) 
            options.data += "&";
         else 
            options.data = "";
        
        options.data += "csrfmiddlewaretoken=csrf_token";
    
);

【讨论】:

【参考方案4】:

我发现解决此问题的一种方法是使用预先存在的表单作为 AJAX 数据的起点。

<form id="ajax_form" stye="display: none;">% csrf_token %</form>

然后你可以通过 JQuery 的 Serialize 函数在你的 javascript 中使用它:

var data = $('#ajax_form').serialize();
data += "&mydata=69";

您甚至可以在该隐藏表单中使用隐藏字段,这样您就不必使用字符串连接来构建您的 POST 数据。

【讨论】:

【参考方案5】:

如果您使用@csrf_protect 装饰器,请确保带有表单的视图和正在发布数据的视图都使用该装饰器。

我遇到了类似的问题。我在帖子视图上只有@csrf_protect ,它在本地测试良好,但是当我上线时遇到一个 403 验证失败的问题,将装饰器添加到他的页面视图修复了这个

【讨论】:

以上是关于Django 1.3 中的 Ajax CSRF 问题的主要内容,如果未能解决你的问题,请参考以下文章

在 Django 中的 ajax POST 期间被禁止(CSRF 令牌丢失或不正确。)

Django中的CSRF

禁止(CSRF 令牌丢失或不正确。)Django

如何在Django使用ajax的POST

jQuery + AJAX + Django = CSRF ? [复制]

Django与CSRF AJAX