Django服务器报告“禁止CSRF令牌丢失或不正确”,尽管正确发送了令牌?

问题描述

我正在尝试向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)
        });

incomingTokendocument.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()对象。