【问题标题】:Keep getting 403 "CSRF token missing or incorrect" in Django + Vue setup在 Django + Vue 设置中不断收到 403“CSRF 令牌丢失或不正确”
【发布时间】:2021-09-27 10:50:19
【问题描述】:

我搜索了其他类似的问题,但没有一个解决方案有效,也没有让我了解可能发生的事情。

我的设置是一个 Vue 前端(有自己的路由)加上一个 Django 后端和 API。我尝试的任何 GET 路由都按预期工作,但 POST 需要 CSRF 保护。我有一个自定义渲染函数,我调用了指向索引的路由(然后将由 Vue 处理),我在其中提供 CSRF 令牌,如下所示:

def custom_render(request):
    # ...

    # from django.middleware.csrf
    get_token(request)

    # from django.shortcuts
    return render(request, template)

这会使用 CSRF 令牌设置一个 cookie csrftoken,这似乎可以正常工作,正如我在 devtools 中看到的那样,如果我删除它,刷新时它会再次出现。这是我相关的 Django settings.py:

# This one is True in production, but for now I'm testing locally
CSRF_COOKIE_SECURE = False

CSRF_HEADER_NAME = "X-CSRFToken"

# I tried playing with both these options' values to no avail
CSRF_USE_SESSIONS = False
CSRF_COOKIE_HTTPONLY = False


MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "django.middleware.common.BrokenLinkEmailsMiddleware",
]

在 Vue 方面(Typescript),我正在使用这个发送请求:

function getCsrfToken() {
  return document.cookie.match("(^|;)\\s*" + "csrftoken" + "\\s*=\\s*([^;]+)")?.pop()
}

fetch(
  "api/my-route/",
  {
    method: "POST",
    headers: {
      "X-CSRFToken": getCsrfToken(),
      "Content-Type": "application/json",
      "Accept": "application/json",
    },
    mode: "same-origin",
    body: JSON.stringify(dataToSend),
  },
)

这也可以按预期工作,正如我在 devtools 中看到的那样,请求确实包含 X-CSRFToken 标头,其内容与 csrftoken cookie 相同。但是,响应仍然是 403,声称令牌丢失或不正确。我不确定 Django 是否认为它丢失了,或者它是否认为它不正确,所以我不确定如何继续。连接调试器是不切实际的,因为我不知道应该在什么内部方法处停止执行,所以我被卡住了。

编辑:我最近尝试的其他事情:

  • 在后端,用我的主视图上的@ensure_csrf_cookie 装饰器替换我自定义渲染函数中get_token() 的使用。奇怪的是,这没有导致 csrf cookie 按预期设置。
  • 再次在后端,将@csrf_protect 装饰器添加到主视图。这 确实 导致设置了 csrf cookie,尽管我不太明白为什么。无论如何,这并没有解决问题。
  • 在前端,将csrfmiddlewaretoken 字段添加到POST 请求的正文中,以令牌作为值。
  • 再次在前端,使用与 Django 文档中显示的完全相同的功能获取令牌,而不是我自定义的。

不幸的是,这些都没有改变结果:当我确实有可用的 cookie 时,它​​的值似乎不能满足 Django。

【问题讨论】:

  • 如果你使用 django 文档告诉你获取 csrf 令牌的suggested way,你能试试它是否有效吗?
  • @bdbd 请查看问题底部的编辑以及我尝试过的最新内容,包括您的建议。

标签: python django vue.js csrf django-csrf


【解决方案1】:

我发现了问题:我的设置中的CSRF_HEADER_NAME = "X-CSRFToken" 没有考虑到这样一个事实,即“显式优于隐式”的 Django 隐式规范了所有标头名称,以便请求中的令牌将结束up 看起来像 HTTP_X_CSRFTOKEN,但不会费心对自定义名称做同样的事情,所以在 Django 比较它们时两者不会匹配。

【讨论】:

    猜你喜欢
    • 2013-08-15
    • 2013-12-03
    • 1970-01-01
    • 2015-10-15
    • 2017-09-10
    • 1970-01-01
    • 2021-07-14
    • 2018-11-05
    • 2019-12-22
    相关资源
    最近更新 更多