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 令牌丢失或不正确。)