首页 文章

如何从Django中检索/提供CSRF令牌作为API

提问于
浏览
5

我在 api.somecompany.com 说,但有一个React.js前端(在 www.somecompany.com )没有Django提供AJAX请求 .

我可以't, therefore, use Django'的传统方法让模板包含这样的CSRF令牌 <form action="." method="post">{% csrf_token %}

我可以向Django REST Framework的 api-auth\login\ url发出请求,它将返回此 Headers : Set-Cookie:csrftoken=tjQfRZXWW4GtnWfe5fhTYor7uWnAYqhz; expires=Mon, 01-Aug-2016 16:32:10 GMT; Max-Age=31449600; Path=/ - 但我无法检索此cookie以使用 X-CSRFToken (我的理解属于单独的子域)发回我的AJAX请求,并且它似乎没有自动包含 .

这是我的相关代码:

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

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)) {
            xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
        }
    }
});

当页面加载时我调用它以确保我有一个令牌:

$.ajax(loginUrl, { method: "OPTIONS", async: false })
    .done(function(data, textStatus, jqXHR) {
        console.log(jqXHR)
        app.csrftoken@ = $.cookie("csrftoken")
        console.log($.cookie("csrftoken"))
        console.log(app.csrftoken)
    })
    .fail(function(jqXHR, textStatus, errorThrown) {
        console.log(jqXHR)
    });

这不是很干净,但我还没有向自己证明这个概念 .

当前端和后端位于不同的端口/域上时,对CSRF进行身份验证/保护的“正确”方法是什么?

1 回答

  • 1

    事实上,您可以使用允许的请求来源的白名单来使用CSRF保护 .

    为了使这项工作,您将不得不使用 Cross-Origin Resource Sharing (CORS) . 为实现这一目标,我概述了如何在跨源HTTP请求标头中使用某些构建版本的great gist . 如果需要,您可以通过这种方式通过中间件插入CSRF令牌,方法是更改请求的原始参考值 .

    django-cors-headers应用程序为您执行此操作 . 如果您有兴趣,可以看看他们如何在their middleware file中协商CSRF令牌 .

    有关详细信息,请参阅Django REST CORS Docs(他们建议使用django-cors-headers) .

    如果您仍有困难,请尝试:

    • 将AJAX请求的crossDomain参数设置为 True . 有时,jQuery赢得了't process the request if this isn' t指定 .

    • 如果您仍然没有在请求中收到令牌标头,请尝试在您的view方法附近添加ensure_csrf_cookie()装饰器 . 偶尔,当页面上没有 {% csrf_token %} 模板标签时(如果您在请求中包含令牌) .

相关问题