根据django文档,对于1.3中的ajax post请求(至少使用Jquery),我们只需要将此snippet添加到主js文件中。此代码段从cookie获取csrftoken,然后为所有ajax请求设置它。这是有效的,但是如果csrftoken在cookie中不存在怎么办?我认为render_to_response和渲染都会自动检查会话中是否有csrftoken,如果不存在令牌,则为我们设置。但他们不是。所以,我需要自己实现它?或者可能有另一种方法来处理ajax csrf保护?
答案 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验证失败的问题,添加了装饰器,页面视图修复了这个