2015-08-03 3 views
5

Я работаю над проектом, использующим Django REST Framework в качестве бэкэнд (скажем, в api.somecompany.com, но имеет интерфейс React.js (по адресу www.somecompany.com) не обслуживается Джанго, что делает AJAX запросы.Как получить/предоставить токен CSRF в/из Django как API

я не могу, поэтому, использовать традиционный метод Джанго иметь шаблон включает маркер CSRF, как этот <form action="." method="post">{% csrf_token %}

я могу сделать запрос на api-auth\login\ URL Django REST Рамочной основы , который вернет этот заголовок: Set-Cookie:csrftoken=tjQfRZXWW4GtnWfe5fhTYor7uWnAYqhz; expires=Mon, 01-Aug-2016 16:32:10 GMT; Max-Age=31449600; Path=/ - но я не могу извлечь этот файл cookie для отправки обратно с помощью моих запросов AJAX h X-CSRFToken (мое понимание относится к отдельному субдомену), и оно, кажется, не включается автоматически.

Вот мой соответствующий код:

// 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) 
     [email protected] = $.cookie("csrftoken") 
     console.log($.cookie("csrftoken")) 
     console.log(app.csrftoken) 
    }) 
    .fail(function(jqXHR, textStatus, errorThrown) { 
     console.log(jqXHR) 
    }); 

Это не совсем чистый, но я не доказанный концепция для меня еще.

Что такое «правильный» способ аутентификации/защиты от CSRF, когда интерфейс и бэкэнд находятся на разных портах/доменах?

ответ

1

Вы можете, по сути, сделать эту работу с защитой CSRF, используя белый список разрешенных источников запросов.

Для выполнения этой работы вам необходимо использовать Cross-Origin Resource Sharing (CORS). Чтобы достичь этого, я бы рекомендовал создать класс промежуточного программного обеспечения, который будет устанавливать ваши учетные данные для совместного доступа. Существует great gist, в котором описывается, как использовать некоторые из сборщиков кросс-заголовков HTTP-заголовков. Вы можете, если хотите, вставить маркер CSRF с помощью промежуточного программного обеспечения таким образом, изменив исходные значения для запроса.

Приложение django-cors-headers делает это за вас. Вы можете видеть, как они согласовали токены CSRF в their middleware file, если вам интересно.

Подробнее об этом см. В разделе Django REST CORS Docs (они рекомендуют использовать django-corors-headers).

Если вы все еще испытываете трудности, попробуйте:

  1. установки параметра вашего запроса AJAX crossDomain в True. Иногда jQuery не обрабатывает запрос, если это не указано.
  2. Если вы все еще не получаете заголовок маркера в запросе вообще, попробуйте добавить декоратор ensure_csrf_cookie() вокруг вашего метода просмотра. Иногда, если на странице нет тега шаблона {% csrf_token %} (если вы не показываете форму), Django вообще не будет включать токен в запрос.
+0

Я думаю, что у меня уже есть это покрытие - моя просьба не терпит неудачу по причинам CORS. Моя проблема, насколько я могу судить, заключается в том, что мой первый запрос (опция «ОПЦИИ») не устанавливает файл cookie 'csrftoken', поэтому я не могу его прочитать, чтобы добавить его в качестве заголовка, или он автоматически отправляется с последующим запрос. Выполнение запроса напрямую (не используя AJAX) правильно устанавливает cookie. Есть что-то, запрещающее настройку cookie? – jimbofreedman

+0

Если это так, я могу подумать о двух других вещах, которые могут пойти не так: во-первых, убедитесь, что параметр 'crossDomain' запроса AJAX имеет значение« True », как описано в api.jquery.com/jQuery. Аякс. Также вероятно, что если вы не включаете тег шаблона CSRF на странице, которую вы просматриваете (например, страница не имеет формы), Django может не включать маркер в заголовке по умолчанию. Вы можете использовать 'decor_csrf_cookie (view)' decorator вокруг вашего представления, чтобы заставить это (см. Https://docs.djangoproject.com/en/dev/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie) – ilkahnate

Смежные вопросы