15

我正在测试发出 POST ajax 请求,但由于没有 csrftoken,我得到了 403。我关注了文档,但是它仍然不起作用,我发现名为 csrftoken 的 cookie 是empty,这意味着$.cookie("csrftoken") return null

有人可以告诉我原因以及如何设置csrftoken到 cookie 中吗?

4

5 回答 5

22

我认为您应该提供如何在 HTML/JS 代码和中间件设置中获取 csrf 令牌的代码。

首先,您应该检查是否django.middleware.csrf.CsrfViewMiddleware已打开。

我有一个类似的问题,当我在 python 代码request.META.get('CSRF_COOKIE')中获取令牌时。

当您在模板中使用此标记时 - {% csrf_token %}Django 注意到该标记已呈现并将 Cookie 设置为CsrfViewMiddleware.process_response. 如果您以其他方式获取令牌值,Django 将错过此标志。因此它会为您生成一个令牌,但不会设置相应的 cookie。

我在代码中有 2 个解决方法。您应该将它添加到用于生成带有 JS 代码的模板的视图中。

1.可以强制Django设置CSRF Coo​​kie:

# Force updating CSRF cookie
request.META["CSRF_COOKIE_USED"] = True

2.如果你调用,Django 会自动设置 CSRF_COOKIE_USEDget_token

from django.middleware.csrf import get_token
# don't use direct access to request.META.get('CSRF_COOKIE')
# in this case django will NOT send a CSRF cookie. Use get_token function
csrf_token = get_token(request)

每个解决方案都应该单独工作。我建议使用get_token

于 2012-11-16T09:38:50.700 回答
15

您可能想要使用ensure_csrf_cookie视图装饰器(从 Django 1.4 开始可用)。csrftoken即使您不使用{{ csrf_token }}模板标签,这也会设置cookie。

于 2013-04-10T06:52:24.603 回答
5

我遇到了同样的问题($.cookie('csrftoken') 返回了'undefined')。

问题出在我的 Django 配置中,我评论了以下行并且它有效:

#CSRF_COOKIE_HTTPONLY = True  # Prevent client-side JavaScript access to the CSRF cookie
于 2014-10-07T14:57:39.967 回答
2

扩展o_c 的答案:通过注释该CSRF_COOKIE_HTTPONLY行,csrf_token 值不再是“未定义”(在 Firefox firebug 中),而是显示为“真实”值,例如“qGuPe2Q7...等”。

Ajax 请求不再因403 Forbidden错误而被拒绝并被正确执行(前提是在 AJAX 标头中设置了 csrf_token)。

        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                 if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                 xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
             }
        });
于 2016-04-18T19:26:45.260 回答
2

首先,如果您正在设计应用程序,最好在标头或 POST 请求中使用 csrf Token,而不是在 cookie 中,因为:

  • 所有表单都必须动态地将值添加到其 HTML 中。任何 AJAX POST 还必须包含该值。
  • cookie 将针对每个请求提交(即所有 GET 的图像、CSS、JS 等,不涉及 CSRF 过程)增加请求大小。

如果你想在 django 中强制使用 cookie,你总是可以:

request.META["CSRF_COOKIE_USED"] = True

如果您没有在任何地方使用 {% csrf_token %} 在您的项目中。根据 [documentation][1],您无需执行任何其他操作,只需编写一个简单的 javascript 代码即可。其实这不是真的。您必须"request.META['CSRF_COOKIE_USED'] = True"在每个视图中放置线条(或编写适当的装饰器)。

于 2016-04-18T19:46:54.453 回答