【问题标题】:Django - AJAX not working due to csrf token not working on windowsDjango - 由于 csrf 令牌不能在 Windows 上工作,AJAX 不能工作
【发布时间】:2015-10-02 23:59:37
【问题描述】:

我在 Linux 上开发了我的应用程序,并且 AJAX 请求工作正常。我已将应用程序拉到 Windows 机器上,但 AJAX 请求失败,我只收到 403 Forbidden 错误。从网上看,我认为是csrf令牌的问题。在 Linux 中,我可以在 AJAX 请求的 Cookies 下看到csrftoken:"AjQzJy3tRZ2awslgdibkDTvQgANFQKmP"。我没有在 Windows 中看到任何 cookie 设置。

这是我用来获取 csrf cookie 的 Javascript 代码。来自https://docs.djangoproject.com/en/1.8/ref/csrf/

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;
}

这是我提交 AJAX 请求的地方:

function refreshInformation(){
$.ajax({
    type: "POST",
    url: "get_flows_info",
    data: {
           csrfmiddlewaretoken: getCookie('csrftoken')
    }
    dataType : "json",
    async : true,
    error : function(data){
        alert('AJAX error:' + data);
    },
    success : function(json_data){
            // do stuff...
    },
}); 
}

这是被请求的视图:

def get_flows_info(request):
    if request.is_ajax():

          # do stuff...

        return HttpResponse(json.dumps(ret), content_type='application/json')

我发现了这个:Django CSRF check failing with an Ajax POST request 但 jQuery 没有任何区别。

有什么帮助吗?

谢谢。

【问题讨论】:

  • 您是否尝试发送X-CSRFToken 标头?
  • 另外,getCookie('csrftoken') 调用返回什么?我假设CSRF_COOKIE_NAME 有它的默认值。
  • 在 Linux 上返回 AjQzJy3tRZ2awslgdibkDTvQgANFQKmP,在 Windows 上返回 null...

标签: ajax django


【解决方案1】:

这是可以做的:

  1. 检查 CSRF 令牌 cookie 名称。

    更多信息请参见CSRF_COOKIE_NAME

  2. ensure_csrf_cookie 装饰器添加到您的视图(呈现页面的那个)。

    根据the docs

    警告

    如果您的视图未呈现包含 csrf_token 模板标签的模板,则 Django 可能不会设置 CSRF 令牌 cookie。这在表单被动态添加到页面的情况下很常见。为了解决这种情况,Django 提供了一个视图装饰器来强制设置 cookie:ensure_csrf_cookie()

  3. 假设 CSRF 令牌 cookie 名称为 csrftoken,尝试发送 X-CSRFToken 标头。

    $.ajax({
        // Your options here.
        headers: {'X-CSRFToken': getCookie('csrftoken')}
    });
    

阅读Cross Site Request Forgery protection了解更多信息。

【讨论】:

  • 感谢您的回复,但 getCookie 返回 null,因此不起作用。
  • @BelegNeurion 通过在设置中打印 CSRF_COOKIE_NAME 检查 CSRF 令牌 cookie 名称。
  • 我应该在哪里打印?我尝试了print(CSRF_COOKIE_NAME),在那里我调用了我的索引视图,但它说它没有定义。
  • @BelegNeurion 在任何视图中打印它然后访问它。首先导入设置(from django.conf import settings),然后调用print settings.CSRF_COOKIE_NAME
  • @BelegNeurion 不错。你可以在浏览器的控制台中执行document.cookie.indexOf('csrftoken') 吗?
【解决方案2】:

我所做的只是what the Doc suggests:为所有 Ajax 请求添加一个标头,而不是在每个 ajax 请求中发布 csrftoken。它适用于我(仅在 Linux 中测试过)

第一部分是像你做的那样获取cookie。

<script type="text/javascript">
    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');
....

然后,按照文档的建议,使用这种方法:

function csrfSafeMethod(method) {
        // these HTTP methods do not require CSRF protection
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }

$.ajaxSetup({
   beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

最后,像往常一样进行 ajax 调用,不添加 csrftoken 作为附加参数。

当您想在同一页面中进行多个 ajax 调用时,它很有用。也推荐。而且,如果之前你没有 CSRF 保护,现在你必须添加它,它不涉及更改现有代码。

在使用 ajax 的每个页面中重复这些行,而不是在每个 ajax 调用中重复标记。

【讨论】:

    猜你喜欢
    • 2018-07-06
    • 2013-03-12
    • 2015-01-02
    • 2018-06-18
    • 2015-01-10
    • 2016-01-01
    • 1970-01-01
    • 2019-10-08
    相关资源
    最近更新 更多