使用fetch post请求进行正确的Django CSRF验证

时间:2017-04-25 09:00:26

标签: javascript django django-csrf fetch-api

我正在尝试使用JavaScript的fetch库向我的Django应用程序提交表单。但无论我做什么,它仍然会抱怨CSRF验证。

关于Ajax的文档提到了我已经尝试过的a header

我也尝试抓取the token from the templatetag并将其添加到表单数据中。

这两种方法似乎都不起作用。

以下是包含表单值和标题的基本代码:

let data = new FormData();
data.append('file', file);;
data.append('fileName', file.name);
// add form input from hidden input elsewhere on the page
data.append('csrfmiddlewaretoken', $('#csrf-helper input[name="csrfmiddlewaretoken"]').attr('value'));
let headers = new Headers();
// add header from cookie
const csrftoken = Cookies.get('csrftoken');
headers.append('X-CSRFToken', csrftoken);
fetch("/upload/", {
    method: 'POST',
    body: data,
    headers: headers,
})

我能够使用JQuery,但想尝试使用fetch

2 个答案:

答案 0 :(得分:7)

想出来了。问题是fetch doesn't include cookies by default

简单的解决方案是将credentials: "same-origin"添加到请求中并且它可以正常工作(使用表单字段但没有标题)。这是工作代码:

let data = new FormData();
data.append('file', file);;
data.append('fileName', file.name);
// add form input from hidden input elsewhere on the page
data.append('csrfmiddlewaretoken', $('#csrf-helper input[name="csrfmiddlewaretoken"]').attr('value'));
fetch("/upload/", {
    method: 'POST',
    body: data,
    credentials: 'same-origin',
})

答案 1 :(得分:3)

您的问题非常接近成功。如果您不想使用form方法,这是一种 json 方式。顺便说一句,@ Cory的form方法非常简洁。

  1. 带有第三个库的整洁方式
let data = {
    'file': file,
    'fileName': file.name,
};
// You have to download 3rd Cookies library
// https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
let csrftoken = Cookies.get('csrftoken');
let response = fetch("/upload/", {
    method: 'POST',
    body: JSON.stringify(data),
    headers: { "X-CSRFToken": csrftoken },
})

2。 另一种麻烦的方法,但没有任何第3个库

let data = {
    'file': file,
    'fileName': file.name,
};
let csrftoken = getCookie('csrftoken');
let response = fetch("/upload/", {
    method: 'POST',
    body: JSON.stringify(data),
    headers: { "X-CSRFToken": csrftoken },
})

// The following function are copying from 
// https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var 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;
}