我搜索了其他类似的问题,但没有一个解决方案奏效,也没有让我对可能发生的事情有任何洞察
我的设置是一个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令牌的cookiecsrftoken
,它似乎工作正常,因为我可以在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中看到的那样,这也是预期的效果,请求确实包含与csrftoken
cookie内容相同的X-CSRFToken
头。然而,响应仍然是403,声称令牌丢失或不正确。我不确定Django是否认为它丢失了或者它是否认为它不正确,所以我不确定如何继续。连接调试器是不切实际的,因为我不知道应该停止执行的内部方法是什么,所以我被卡住了
编辑:我最近尝试过的其他方法:
get_token()
替换为主视图中的@ensure_csrf_cookie
装饰器。奇怪的是,这并没有导致csrf cookie按预期设置李>@csrf_protect
装饰器添加到主视图。这确实导致了csrf cookie被设置,尽管我不太明白为什么。无论如何,这并没有解决问题李>csrfmiddlewaretoken
字段添加到POST请求主体中,标记作为值李>不幸的是,所有这些都没有改变结果:当我有可用的cookie时,它的值似乎并不满足Django
我发现了一个问题:我设置中的
CSRF_HEADER_NAME = "X-CSRFToken"
没有考虑到Django隐式规范化了所有头名称,使得请求中的标记看起来像HTTP_X_CSRFTOKEN
,但不需要对自定义名称做同样的操作,因此,在Django比较这两种情况时,这两种情况是不匹配的相关问题 更多 >
编程相关推荐