浏览器cookie被清除后,django不会再次发送csrf令牌



在正常情况下,django会通过cookie发送csrf令牌,稍后ajax post方法可以使用该令牌。然而,当我在浏览器(Chrome或Firefox)中清除cookie时,csrf令牌不再发送到浏览器,会话id仍在发送,但没有csrf令牌。有人知道出了什么问题吗?

我通过将{%csrf_token%}添加到我的模板中解决了这个问题,并且SET-COOKIE标头与该页面请求一起出现。事实证明,您必须将{%csrf-token%}放入模板中,才能使服务器通过SET-COOKIE标头发送令牌

查看声明了CsrfViewMiddleware类的django/middleware/csrf.py。正如您在def process_response(self, request, response)中看到的,有三个条件可以阻止cookie设置:

def process_response(self, request, response):
    if getattr(response, 'csrf_processing_done', False):
        return response
    # If CSRF_COOKIE is unset, then CsrfViewMiddleware.process_view was
    # never called, probaby because a request middleware returned a response
    # (for example, contrib.auth redirecting to a login page).
    if request.META.get("CSRF_COOKIE") is None:
        return response
    if not request.META.get("CSRF_COOKIE_USED", False):
        return response
    # Set the CSRF cookie even if it's already set, so we renew
    # the expiry timer.
    response.set_cookie(settings.CSRF_COOKIE_NAME,
                        request.META["CSRF_COOKIE"],
                        max_age = 60 * 60 * 24 * 7 * 52,
                        domain=settings.CSRF_COOKIE_DOMAIN,
                        path=settings.CSRF_COOKIE_PATH,
                        secure=settings.CSRF_COOKIE_SECURE
                        )
    # Content varies with the CSRF cookie, so set the Vary header.
    patch_vary_headers(response, ('Cookie',))
    response.csrf_processing_done = True
    return response

检查为您申请的。

我也遇到了同样的问题。在针对django源进行调试后,原因是:

如果视图未呈现包含csrf_token的模板模板标签,Django可能不会设置CSRF令牌cookie。

两种解决方案:

  • 在模板中添加{% csrf_token %}
  • 对视图使用@ensure_csrf_cookie装饰器

有关详细信息,请参阅django文档。

在我的案例中,问题是VSCode调试器。我通过VSCode调试模式打开服务器,然后打开新的隐姓埋名窗口(显然没有cookie),django停止设置丢失的cookie。当我正常启动服务器时,问题已经解决了。

在大多数情况下,问题是由上次回答中提到的第二次检查引起的

if not request.META.get("CSRF_COOKIE_USED", False):
        return response

这可以通过对视图使用@sensure_csrf_cookie装饰器来解决。如果已使用,则通过检查,并在每次呈现视图时设置/续订cookie。

另请参阅相关主题:在没有表单元素的Django中使用ajax请求

最新更新