【问题标题】:CSRF With Ajax Polling带有 Ajax 轮询的 CSRF
【发布时间】:2013-05-12 14:21:58
【问题描述】:

我有一些 AJAX 每 5 秒轮询一次服务器:

var date = $('article').first().find('time').text();
console.log(date);

setInterval(function() {
    $.post('pollNewEntries', {'date':date}, newEntrySuccess)
}, 5000);

不幸的是,每次 AJAX 尝试轮询服务器时,我都会收到 403 错误,说明我发出了无效的 CSRF 请求。我以前在表单中使用过 AJAX,并在表单中包含了 CSRF 令牌,但我不确定如何使用上面这样的无格式 AJAX 请求来实现。

【问题讨论】:

标签: python ajax django


【解决方案1】:

这个问题的解决方法在 Django 文档中有描述:https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

将此代码添加到您的 js 顶部:

$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        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;
        }
        if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
            // Only send the token to relative URLs i.e. locally.
            xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
        }
    }
});

【讨论】:

    【解决方案2】:

    您需要将csrf 令牌与您的帖子数据一起传递:

    var date = $('article').first().find('time').text();
    console.log(date);
    
    setInterval(function() {
        $.post('pollNewEntries', {'date':date, 'csrfmiddlewaretoken': '{{csrf_token}}'}, newEntrySuccess)
    }, 5000);
    

    【讨论】:

    • 即使它不在 HTML 模板中(它是一个 js 文件)也能工作吗?
    • 哦,我以为它是一个模板。但是你可以做一件事来欺骗它,将它放在&lt;script&gt;标签中,将它放在js.html中,然后将js.html包含在子模板{% include "js.html" %}中。
    【解决方案3】:

    只需在脚本中添加这些行。这是咖啡脚本中的一个示例:

    ### CSRF methods ###
    csrfSafeMethod = (method) ->
      # these HTTP methods do not require CSRF protection
      return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method))
    
    $.ajaxSetup(
      crossDomain: false
      beforeSend: (xhr, settings) ->
        if !csrfSafeMethod(settings.type)
          xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'))
    )
    

    阅读文档:CSRF

    另一方面,正如user1427661 向您建议的那样,使用HTTP GET 方法而不是POST 会更好,因为您只需要读取数据而无需写入任何内容。请参阅W3 docs

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-12
      • 2012-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-24
      • 2017-01-28
      • 2011-04-20
      相关资源
      最近更新 更多