Jquery 和 Django CSRF 令牌

31 投票
3 回答
32547 浏览
提问于 2025-04-17 08:54

我有两个HTML页面。

一个是父页面,另一个是子页面。子页面上有一个提交按钮,点击这个按钮会在父页面上运行代码,发送一个Ajax消息。

我使用$.load()方法加载子页面,然后当按钮被点击时,它会运行一个$.ajax .POST方法。这个POST方法只会把一个JSON字符串传递给Python代码。

在除了IE以外的任何浏览器上,这个操作都很顺利。但是在IE中运行这段代码时,我遇到了关于CSRF令牌的Python/Django错误。

觉得问题可能是因为子页面实际上只是当前页面的刷新,而服务器端的代码正在运行。

有没有人知道我该如何解决这个问题?

谢谢!

3 个回答

9

来自关于CSRF和AJAX的文档

CSRF令牌也会出现在网页的DOM中,但只有在模板中明确使用csrf_token时才会出现。这个令牌的cookie包含了标准的令牌;CsrfViewMiddleware会优先使用cookie,而不是DOM中的令牌。无论如何,只要DOM中有令牌,你就一定会有这个cookie,所以你应该使用cookie!

示例 (同样来自文档)

// using jQuery
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 = jQuery.trim(cookies[i]);
            // 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;
}

var csrftoken = getCookie('csrftoken');

或者可以使用其他任何与cookie交互的方法。

13

如果你要发送一个POST请求的内容,把csrf令牌作为请求头添加可能会更简单。我觉得这种方法更容易理解,因为它不会让请求内容里满是令牌。大多数AJAX请求都会像Django文档建议的那样,把csrf令牌放在请求头里。

function startTest(testId) {
  var payload = JSON.stringify({
    test_id : testId
  });
  $.ajax({
    url: "/test-service/",
    method: "POST",
    headers: {'X-CSRFToken': '{{ csrf_token }}'},
    data: payload,
    dataType: "json"
  }).done(function(response) {
    console.log(response.id + " " + response.name);
  }).fail(function (error) {
      console.log(error);
  });
}
44

你没有在POST请求中传递csrf令牌。试试我在data中做的事情。也就是说,获取csrf令牌(或者用你自己的方法),然后把它放在你的参数里。

$.ajax({
    url : url,
    type: "POST",
    data : {csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value},
    dataType : "json",
    success: function( data ){
        // do something
    }
});

撰写回答