Django без шаблонов + AJAX: обновляется ли токен Django CSRF во время сеанса просмотра?

Моя текущая настройка — AngularJS + Django 1.5, и я полностью отказался от использования механизма шаблонов Django (т.е. бэкэнд — это в значительной степени сервер API).

Поскольку я не использую тег шаблона csrf_token, Django, в свою очередь, не устанавливает и не отправляет в ответ cookie csrftoken. Как указано в официальной документации, декоратор ensure_csrf_cookie() следует использовать, чтобы заставить декорированное представление отправлять файл cookie csrftoken.

Я применил декоратор ensure_csrf_cookie() к представлению, которое обслуживает первый запрос GET, который мой веб-клиент вызывает при начальной загрузке. При этом мой веб-клиент получает токен CSRF и впредь может вызывать небезопасные методы (например, POST) на сервер.

Приведенная выше настройка работает нормально, только если токен CSRF остается неизменным до завершения сеанса просмотра.

Вопрос. Обновляется ли токен Django CSRF во время сеанса просмотра? Если «да», означает ли это, что мне нужно применить декоратор ensure_csrf_cookie() ко всем представлениям, которые у меня есть?


person tamakisquare    schedule 03.12.2013    source источник
comment
1) маловероятно, но ИМХО это деталь реализации, и я не советую полагаться на такое поведение. 2) Просто напишите базовый класс Mixin или View, украшенный ensure_csrf_cookie(), и используйте его в качестве основы для вашего API-представления (вероятно, вы также можете переместить туда много стандартного кода).   -  person Paulo Scardine    schedule 04.12.2013
comment
Спасибо @PauloScardine. Я согласен с тем, что вы сказали. Будут ли какие-либо последствия для безопасности, если файл cookie токена csrf будет установлен для всех ответов сервера?   -  person tamakisquare    schedule 04.12.2013
comment
Насколько я знаю, это не связано с безопасностью, и такие фреймворки, как Django-REST-Framework, делают это — на самом деле вам следует рассмотреть это в следующем проекте, поскольку он покупает вам такие вещи, как нумерация страниц, регулирование и причудливая система разрешений.   -  person Paulo Scardine    schedule 04.12.2013
comment
@PauloScardine - ЛОЛ. Я использую Django REST Framework для текущего проекта. Я люблю это. Но я не вижу, чтобы rest_framework принудительно использовал файл cookie CSRF в своем базовом представлении (например, APIView) или в каком-либо из его общих представлений. Я что-то упускаю? Обратите внимание, что у меня rest_framework v2.3.8.   -  person tamakisquare    schedule 05.12.2013
comment
У вас включена сеансовая аутентификация?   -  person Paulo Scardine    schedule 05.12.2013
comment
@PauloScardine - Да, rest_framework.authentication.SessionAuthentication — единственная схема аутентификации, настроенная для моего проекта.   -  person tamakisquare    schedule 05.12.2013
comment
У меня такая же настройка, и она работает для меня по умолчанию (файл cookie токена csrf отправляется с каждым запросом), поэтому я не могу воспроизвести вашу проблему.   -  person Paulo Scardine    schedule 06.12.2013
comment
@PauloScardine - Ваш сервер API случайно не обслуживает HTML-ответ, включая BrowsableAPI? Глядя на источник django, кажется, что файл cookie csrf автоматически включается только при использовании RequestContext. Мой сервер API обслуживает только JSON, что объясняет, почему мне приходится вручную принудительно включать файл cookie.   -  person tamakisquare    schedule 06.12.2013
comment
бинго; Я использую HTML-код приложения из django, поэтому файлы cookie сеанса присутствуют при начальной загрузке Angular.   -  person Paulo Scardine    schedule 06.12.2013
comment
@PauloScardine - Тайна раскрыта! Это беспокоило меня. Спасибо за ваши ответы. Разместите свой оригинальный комментарий в качестве ответа. Я приму это.   -  person tamakisquare    schedule 06.12.2013


Ответы (2)


1) Обновляется ли токен Django CSRF во время сеанса просмотра?

Похоже, токен CSRF уникален для каждого сеанса, но он исходя из моих наблюдений, у меня нет "официального" источника. С Angular.js я без проблем использую следующий код:

angular.module('app', ...)
  .config(function($httpProvider) {
    var cookies = document.cookie.split(';');
    var csrftoken = _.find(cookies, function(v) { 
                      return v.trim().indexOf('csrftoken=') == 0; 
                    });
    if(csrftoken) {
      $httpProvider.defaults.headers.common['X-CSRFToken'] = csrftoken.split('=')[1];
    }
  })

Поскольку я обслуживаю HTML из Django, к тому времени, когда Angular загрузит файл cookie, он уже будет там.

2) Если «да», означает ли это, что мне нужно применить декоратор sure_csrf_cookie() ко всем представлениям, которые у меня есть?

Вместо этого вы можете попробовать CORS, если CSRF. Отто Ю поддерживает django-cors-headers, который, как известно, корректно работает с API платформы REST.

Некоторые (непроверенные) идеи по применению ensure_csrf_cookie():

  • API-интерфейс обезьяны-патчаView
  • создайте миксин CSRFCookie и добавьте его в свои представления
  • примените ensure_csrf_cookie() к своим базовым классам
person Paulo Scardine    schedule 06.12.2013

Поддерживая идеи @Paulo Scardine о применении ensure_csrf_cookie() (которые я считаю действительными и полезными), я хотел бы добавить к ним новое возможное решение, если вам определенно нужно ensure_csrf_cookie() во всех ваших представлениях. Вы можете написать собственный middleware и реализовать логику внутри ensure_csrf_cookie. Что-то вроде этого:

На вашем app.middleware.py:

from django.middleware.csrf import get_token


class EnsureCsrfCookie(object):

    def process_request(self, request):
        # Forces process_response to send the cookie
        get_token(request)

и, конечно же, в файле settings добавьте промежуточное ПО в файл MIDDLEWARE_CLASSES:

MIDDLEWARE_CLASSES = (
    .,
    .,
    .,
    'app.middleware.EnsureCsrfCookie',
    .,
    .,
    .,
)

Это еще одна идея, чтобы решить эту проблему. Я надеюсь, что это может быть полезно для кого-то в будущем.

person Vladir Parrado Cruz    schedule 16.03.2016