django 在 cookie 中没有 csrftoken

Posted

技术标签:

【中文标题】django 在 cookie 中没有 csrftoken【英文标题】:django no csrftoken in cookie 【发布时间】:2012-11-04 22:42:18 【问题描述】:

我正在测试发出 POST ajax 请求,但由于没有 csrftoken,我得到了 403。我跟着文档,但是还是不行,发现名为csrftoken的cookie是empty,意思是$.cookie("csrftoken")return null

谁能告诉我原因以及如何将csrftoken 设置到cookie 中?

【问题讨论】:

之前有过类似的问题,与 csrf_protect 装饰器有关。如果您从一个页面发布到另一个 url(例如 ajax)并且如果您使用的是 @csrf_protect 装饰器等,请确保两者查看您发布数据的来源以及接收发布数据的 url 以拥有此装饰器。 你的观点,你的模板表单? 【参考方案1】:

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

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

我遇到了类似的问题,在 python 代码中我使用request.META.get('CSRF_COOKIE') 来获取令牌。

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

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

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

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

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

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

【讨论】:

【参考方案2】:

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

【讨论】:

【参考方案3】:

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

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

#CSRF_COOKIE_HTTPONLY = True  # Prevent client-side javascript access to the CSRF cookie

【讨论】:

是的,http-only cookie 无法通过浏览器中的 javascript 访问。 @o_c 你在哪里评论?【参考方案4】:

在o_c's answer 上扩展:通过注释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);
                
             
        );

【讨论】:

如何在前端获取csrftoken【参考方案5】:

首先,如果您正在设计应用程序,最好在标头或 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" 行(或编写适当的装饰器)。

【讨论】:

您是否考虑过对文档提出拉取请求以包含此内容?

以上是关于django 在 cookie 中没有 csrftoken的主要内容,如果未能解决你的问题,请参考以下文章

Django + ReactJS。 Httponly cookie 没有保存在 React 端的浏览器中。我还在两边都给了 withcredentials : true

Django 在同一个视图函数中使用会话和 cookie

Django REST Framework - 没有通过 Response.set_cookie() 调用设置 cookie...?

Django设置cookie中的csrftoken

Django 设置 cookie 中的 csrftoken

如何使用 Django 清除 cookie