繁体   English   中英

Django 1.3中的Ajax CSRF问题

[英]Ajax CSRF problem in Django 1.3

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

如果页面上没有已使用{%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()})

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

如果在模板中使用模板标记{% csrf_token %}来生成请求,或者从django.middleware.csrf调用get_tokenrequest对象作为参数),则cookie将仅包含CSRF令牌。

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

至于Ajax,你应该为每个请求传递csrf标记。 对于jQuery,我使用以下代码:

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM