Django/Ajax: CSRF令牌丢失

3

我有以下ajax函数,在使用select2控件时,一旦超过最小输入长度为3,就会给我一个跨站点伪造请求令牌错误。因此,我尝试向我的数据中添加{ csrfmiddlewaretoken: '{{ csrf_token }}' }。添加csrfmiddlewaretoken后,我仍然收到CSRF令牌缺失或不正确的错误提示。我认为这与我的searchFilter和searchPage函数有关。请问正确的做法是什么?

// 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');

$(document).ready(function () {
    $('.selectuserlist').select2({
      minimumInputLength: 3,
      allowClear: true,
      placeholder: {
        id: -1,
        text: 'Enter the 3-4 user id.',
      },
      ajax: {
        type: 'POST',
        url: '',
        contentType: 'application/json; charset=utf-8',
        async: false,
        dataType: 'json',
        data: { csrfmiddlewaretoken: csrftoken },

        function(params) {
          return "{'searchFilter':'" + (params.term || '') + "','searchPage':'" + (params.page || 1) + "'}";
        },

        processResults: function (res, params) {
            var jsonData = JSON.parse(res.d);
            params.page = params.page || 1;
            var data = { more: (jsonData[0] != undefined ? jsonData[0].MoreStatus : false), results: [] }, i;
            for (i = 0; i < jsonData.length; i++) {
              data.results.push({ id: jsonData[i].ID, text: jsonData[i].Value });
            }

            return {
              results: data.results,
              pagination: { more: data.more,
              },
            };
          },
      },
    });

  });

我的视图有POST方法和csrf_token。

  {% block content %}
  <form action = "{% url 'multiresult' %}" form method = "POST">
      {% csrf_token %}
  {% block extra_js %}
      {{ block.super }}
      {{ form.media }}

控制台的响应是:

禁止访问(缺少或不正确的 CSRF 令牌):/search/multisearch/ [29/Mar/2018 09:14:52] "POST /search/multisearch/ HTTP/1.1" 403 2502


Django文档解释了如何设置一个头部用于ajax请求。由于您的ajax请求提交json编码数据,因此必须使用该方法。 - Alasdair
3个回答

12

你需要将 csrf_token 包含在头部中:

var csrftoken = $("[name=csrfmiddlewaretoken]").val();

//example ajax
$.ajax({
    url: url,
    type: 'POST',
    headers:{
        "X-CSRFToken": csrftoken
    },
    data: data,
    cache: true,
});

如果您没有使用 SSL,请确保 CSRF_COOKIE_SECURE = False。 如果您正在使用 SSL,请将其设置为 True

是否要为 CSRF Cookie 使用安全 Cookie。如果设置为 True,则该 Cookie 将被标记为“安全”,这意味着浏览器可能会确保 Cookie 只能与 HTTPS 连接一起发送。


我应该在我的settings.py中添加CSRF_COOKIE_SECURE吗?我没有使用SSL。 - user1470034
是的,将其添加到设置中。 - King Reload
我按照你的建议做了,成功解决了我的CSRF错误。但我的结果还有其他问题,谢谢你正确引导我。 - user1470034
没问题 :) 我很高兴能够帮助。 - King Reload
csrftoken在哪里?Django太烂了。 - Alston

3
一个混合了JS和Django模板语言的方法帮助解决了这个问题。
  $.ajax({
         type: 'POST',
         headers:{
        "X-CSRFToken": '{{ csrf_token }}'
         }
  })

1

刚刚修改了下面的代码行,它更简单,因为你不必涉及模板。你提供的js片段已经有csrf值。

  data: { csrfmiddlewaretoken: '{{ csrf_token }}' },
      // INTO
  data: { csrfmiddlewaretoken: csrftoken },

我已按照您的建议进行操作,但仍然遇到403错误的相同问题。我已添加了上述更改。 - user1470034
此外,在 select2 控件中,当最小输入长度为 3 时会出现 403 错误。 - user1470034

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接