【发布时间】: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