[英]Django server reporting "Forbidden (CSRF token missing or incorrect.)" despite sending token correctly?
I am trying to send a JSON POST request to my Django server.我正在尝试向我的 Django 服务器发送 JSON POST 请求。
It reports this error: Forbidden (CSRF token missing or incorrect.):
它报告此错误:
Forbidden (CSRF token missing or incorrect.):
In my Django template, options.html
, I say this:在我的 Django 模板
options.html
,我这样说:
<script>const incomingToken = "{{ csrf_token }}";</script>
And this:和这个:
<input type="hidden" name="csrf-token" id="csrf-token" value="{{ csrf_token }}" />
Then in my JavaScript file that runs in the client I say:然后在我在客户端运行的 JavaScript 文件中,我说:
const serverUrl = "http://127.0.0.1:8000/"
const headers = new Headers({
'Accept': 'application/json',
// 'X-CSRFToken': getCookie("CSRF-TOKEN")
"X-CSRFToken": document.getElementById("csrf-token").value
})
fetch(serverUrl, {
method: "POST",
headers: {
headers
},
mode: "same-origin",
body: JSON.stringify(editorState.expirationDate, editorState.contracts, editorState.theta) // FIXME: server goes "Forbidden (CSRF token missing or incorrect.)" and 403's
}).then(response => {
console.log(incomingToken)
console.log(document.getElementById("csrf-token").value)
console.log(response)
}).catch(err => {
console.log(err)
});
Both incomingToken
and document.getElementById("csrf-token").value
report the same value. incomingToken
和document.getElementById("csrf-token").value
报告相同的值。 So I know I'm getting the correct string for the CSRF token.所以我知道我得到了 CSRF 令牌的正确字符串。
How can this be?怎么会这样? What am I doing wrong?
我究竟做错了什么?
For reference, here is what I see in another thread on the subject :作为参考,这是我在另一个主题中看到的内容:
const csrfToken = getCookie('CSRF-TOKEN');
const headers = new Headers({
'Content-Type': 'x-www-form-urlencoded',
'X-CSRF-TOKEN': csrfToken // I substitute "csrfToken" with my code's "incomingToken" value
});
return this.fetcher(url, {
method: 'POST',
headers,
credentials: 'include',
body: JSON.stringify({
email: 'test@example.com',
password: 'password'
})
});
Instead of running a function to retrieve the value from a cookie, I simply insert the value Django embeds using {{ csrf_token }}
.我没有运行函数来从 cookie 中检索值,而是简单地使用
{{ csrf_token }}
插入 Django 嵌入的值。 I also tried pasting the code from the top answer in this thread , including function getCookie(name)
.我还尝试粘贴此线程中顶级答案中的代码,包括
function getCookie(name)
。 Nothing.没有。 Client still says
POST http://127.0.0.1:8000/ 403 (Forbidden)
, server still cries with the same Forbidden (CSRF token missing or incorrect.)
error.客户端仍然说
POST http://127.0.0.1:8000/ 403 (Forbidden)
,服务器仍然以相同的Forbidden (CSRF token missing or incorrect.)
错误哭泣。
Suggestions please!请提出建议!
Update:更新:
So I tried a function from Django's CSRF protection docs page that reads:所以我尝试了Django 的 CSRF protection docs page中的一个函数,内容如下:
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
For whatever reason, this function returns a different value when I run getCookie("csrftoken")
-- a value that is different from that of what is embedded by {{ csrf_token }}
.无论出于何种原因,当我运行
getCookie("csrftoken")
时,此函数返回不同的值——该值与{{ csrf_token }}
嵌入的值不同。 Dunno what to make of that.不知道该怎么做。 Neither one works when inserting it into
"X-CSRFToken"
in my headers.将其插入我的标题中的
"X-CSRFToken"
时,两者都"X-CSRFToken"
。
I found the solution to the problem.我找到了问题的解决方案。
The solution came when I ignored much of what I found on StackOverflow and instead opted just to use the Django docs.当我忽略在 StackOverflow 上发现的大部分内容而选择仅使用 Django 文档时,解决方案就出现了。
I had my code written as it is in my OP -- see how it makes headers out of new Headers()
?我在我的 OP 中编写了我的代码——看看它是如何用
new Headers()
制作标题的? And how the fetch
has serverUrl
plugged in as the first argument? fetch
如何将serverUrl
作为第一个参数插入?
Well, I changed it so that it reads like this:好吧,我把它改成了这样:
const serverUrl = "http://127.0.0.1:8000/"
const request = new Request(serverUrl, { headers: { 'X-CSRFToken': getCookie("csrftoken") } })
fetch(request, {
method: "POST",
mode: "same-origin",
body: JSON.stringify(editorState.expirationDate, editorState.contracts, editorState.theta)
}).then(response => {
console.log(response)
}).catch(err => {
console.log(err)
});
And it worked!它奏效了!
The difference was using the new Request()
object in the fetch
argument.不同之处在于在
fetch
参数中使用了new Request()
对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.