Django 1.9 AJAX 表单 CSRF 令牌 403 错误 - “未设置 CSRF cookie”

Posted

技术标签:

【中文标题】Django 1.9 AJAX 表单 CSRF 令牌 403 错误 - “未设置 CSRF cookie”【英文标题】:Django 1.9 AJAX form CSRF token 403 error - "CSRF cookie not set" 【发布时间】:2016-06-22 10:53:19 【问题描述】:

我在 SO 上看到了很多关于此的内容,但没有什么可以解决我的问题。

问题:

启用 CSRF 中间件后,Django 在 AJAX 表单请求中以 403 响应,说明:

“未设置 CSRF cookie。”

在documentation之后,实现了一个JS功能,它设置了自定义“X-CSRFToken”标头。

它按预期工作,从浏览器获取 "csrftoken" cookie 并将其与 AJAX 请求一起发布:

x-csrftoken: 1a0u7GCQG0wepZHQNThIXeYpMy2lZOf2

但响应仍然是 403。

尝试过的解决方案:

我已经尝试了所有可以在 SO 或网络上找到的东西,特别是:

检查中间件是否启用:

MIDDLEWARE_CLASSES = [
    ...
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    ...
]

启用 cookie 的不同浏览器;

@ensure_csrf_cookie装饰我的视图;

在我的模板中设置% csrf_token %

使用render 快捷方式获取正确的请求上下文;

在我的settings.py中设置自定义CSRF_COOKIE_NAMECSRF_HEADER_NAME

显式设置CSRF_COOKIE_SECURE = FalseCSRF_COOKIE_HTTPONLY = False

显式设置CSRF_TRUSTED_ORIGINS设置;

在开发和生产服务器上测试;

在我看来,即使是 request.META["CSRF_COOKIE_USED"] = True,正如有人建议的那样。

还是一无所获。

标题:

如果我在我看来使用 @csrf_exemptprint(request.META),很明显自定义标头 "X-CSRFToken" 存在于请求中,并根据 Django 文档格式化,带有“HTTP_”前缀, 用下划线替换连字符,全部大写:"HTTP_X_CSRFTOKEN"

更重要的是,它的值与 Django 设置的 cookie 匹配。

Cookie:

奇怪的是,如果我尝试 print(request.COOKIES) 在我看来,在页面和表单加载我可以看到 "csrftoken" cookie 那里,但字典是 AJAX 请求空。会不会是问题?

急于找出真正的问题所在。感谢您阅读本文。

【问题讨论】:

你能展示你的实际视图和javascript吗? 你用什么来发送 AJAX 请求? jQuery? @Smile0ff:获取 API。 大声笑,阅读您的调试过程有点不可思议,因为我按照基本完全相同的顺序执行了完全相同的步骤 :) 【参考方案1】:

好的,那么问题就很简单了:

Fetch API 默认不发送凭据。根据MDN:

Request接口的credentials只读属性表示 用户代理是否应该从其他域发送 cookie 跨域请求的情况。这类似于 XHR 的 withCredentials 标志,但具有三个可用值。

默认是omit,它从不发送cookies。您只需将same-origin 添加到您的fetch() 函数参数中:

fetch(formUrl, 
    ...
    credentials: 'same-origin',
    ...
)

你会很高兴的:)

【讨论】:

以上是关于Django 1.9 AJAX 表单 CSRF 令牌 403 错误 - “未设置 CSRF cookie”的主要内容,如果未能解决你的问题,请参考以下文章

django:csrf_token 用于单个页面上的多个表单和 ajax 请求

Django - 在同一个模板(ajax 和表单)中处理多个 CSRF 令牌禁止(CSRF 令牌丢失或不正确。)

没有表单的 Django CSRF 令牌

30_Django中关于使用ajax发送请求中`csrf_token`的问题和解决

Django-ajax:CSRF 验证失败。请求中止

Django CSRF与auth模块