Django 1.3中的Ajax CSRF问题

时间:2011-03-31 12:09:06

标签: ajax django csrf

根据django文档,对于1.3中的ajax post请求(至少使用Jquery),我们只需要将此snippet添加到主js文件中。此代码段从cookie获取csrftoken,然后为所有ajax请求设置它。这是有效的,但是如果csrftoken在cookie中不存在怎么办?我认为render_to_response和渲染都会自动检查会话中是否有csrftoken,如果不存在令牌,则为我们设置。但他们不是。所以,我需要自己实现它?或者可能有另一种方法来处理ajax csrf保护?

5 个答案:

答案 0 :(得分:11)

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

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

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

然而,

无需等待。只需将此行添加到任何包含AJF帖子CSRF表单的视图:

request.META["CSRF_COOKIE_USED"] = True

示例:

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

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

答案 1 :(得分:3)

如果模板中使用模板标记{% csrf_token %}生成请求,或者调用get_token(使用request对象,则您的Cookie将仅包含CSRF令牌作为参数)来自django.middleware.csrf

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

答案 2 :(得分: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}}";
    }
});

答案 3 :(得分:1)

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

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

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

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

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

答案 4 :(得分:1)

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

我有类似的问题。我在post视图上只有@csrf_protect,它在本地进行了很好的测试,但是当我上线时,得到了403验证失败的问题,添加了装饰器,页面视图修复了这个