问题描述
我正在尝试向Django服务器发送JSON POST请求。
它报告此错误:Forbidden (CSRF token missing or incorrect.):
在我的Django模板options.html
中,我这样说:
<script>const incomingToken = "{{ csrf_token }}";</script>
这:
<input type="hidden" name="csrf-token" id="csrf-token" value="{{ csrf_token }}" />
然后在客户端中运行的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)
});
incomingToken
和document.getElementById("csrf-token").value
都报告相同的值。所以我知道我为CSRF令牌获取了正确的字符串。
怎么可能?我在做什么错了?
作为参考,这是我在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: '[email protected]',password: 'password'
})
});
我只运行{{ csrf_token }}
来插入Django嵌入的值,而不是运行从cookie检索值的函数。我还尝试粘贴来自the top answer in this thread的代码,包括function getCookie(name)
。没有。客户端仍然说POST http://127.0.0.1:8000/ 403 (Forbidden)
,服务器仍然在哭,并出现相同的Forbidden (CSRF token missing or incorrect.)
错误。
请提出建议!
更新:
所以我尝试了Django's 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;
}
无论出于何种原因,当我运行getCookie("csrftoken")
时,此函数都会返回不同的值-该值与{{ csrf_token }}
嵌入的值不同。不知道该怎么做。将其插入标头中的"X-CSrftoken"
时,都无效。
解决方法
我找到了解决问题的方法。
当我忽略了我在StackOverflow上发现的大部分内容,而是选择仅使用Django文档时,解决方案就来了。
我在OP中编写了自己的代码-看看它如何使标头来自<CollectionViewSource x:Key="StudentGroup" Source="{Binding Path=Students}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="IsGenius" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<ListView DataContext="{StaticResource StudentGroup}">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}"/>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
?以及new Headers()
是如何插入fetch
作为第一个参数的?
好吧,我对其进行了更改,使其看起来像这样:
serverUrl
成功了!
区别在于在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)
});
参数中使用了new Request()
对象。