it-roy-ru.com

Django токен csrf + Angularjs

У меня Django работает на сервере Apache с использованием mod_wsgi, а также приложение angularjs, обслуживаемое непосредственно Apache, а не Django. Я хотел бы сделать POST вызовы на сервер Django (работает rest_framework), но у меня проблемы с токеном csrf.

Есть ли какой-то способ установить токен с сервера, не добавляя {% csrf token %} в качестве части шаблона (поскольку эти страницы не проходят через Django)?

  1. Я хотел бы иметь возможность получить токен csrf через запрос GET в виде файла cookie.
  2. Я хотел бы иметь возможность затем отправлять POST запросы на сервер Django со значением cookie токена csrf.
64
Preom

У Django и AngularJS уже есть поддержка CSRF, ваша часть довольно проста.

Во-первых, вам нужно включить CSRF в Django, я думаю, что вы уже сделали это, если нет, следуйте Django doc https://docs.djangoproject.com/en/1.5/ref/contrib/csrf/#ajax ,.

Теперь Django установит cookie с именем csrftoken в первом запросе GET и ожидает настраиваемый заголовок HTTP X-CSRFToken в последующих запросах POST/PUT/DELETE.

Для Angular он ожидает файл cookie с именем XSRF-TOKEN и будет выполнять запросы POST/PUT/DELETE с заголовком X-XSRF-TOKEN, поэтому вам нужно немного настроить их, чтобы они совмещались:

$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

Добавьте две вышеупомянутые строки где-нибудь в своем js-коде, для этого подойдет блок module.config ().

Вот и все.

ПРИМЕЧАНИЕ: Это для угловой версии 1.1.5, более старые версии могут нуждаться в другом подходе.

Обновление:

Поскольку приложение angular не обслуживается Django, для того, чтобы установить cookie, приложение angular сначала должно выполнить запрос GET к Django.

110
Ye Liu
var foo = angular.module('foo', ['bar']);

foo.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);

И все сервисы и контроллеры модулей, где используется $ http, будут отправлять запросы с токеном csrf.

60
Nikolay Baluk

После поиска вокруг, то, что работало для меня, было от этот пост со следующим кодом:

angular.module( '[your module name]',
    ... [some dependencies] ...
    'ngCookies',
    ... [other dependencies] ...
)
.run( function run( $http, $cookies ){

    // For CSRF token compatibility with Django
    $http.defaults.headers.post['X-CSRFToken'] = $cookies.get('csrftoken');
})

Это, конечно, после получения куки через GET-запрос от сервера Django. 

Я также рассмотрел некоторые другие ответы здесь, в том числе Е. Лиуна, но не смог найти ничего в официальных документах, где указаны изменения параметров по умолчанию для xsrf в $ httpProvider, кроме этот запрос на получение который не работал для меня на момент написания этого поста.

11
Preom

Я создал приложение Django для своего приложения AngularJS в том же проекте Django, что и мое приложение (REST) ​​API Django, которое обслуживает только файл index.html (который является просто sym.link). Таким образом, файл CSRF Cookie устанавливается без дополнительного запроса GET.

Пожалуйста, ознакомьтесь с моим ответом здесь о одностраничном веб-приложении AngularJS на поддомене A, говорящем с API-интерфейсом Django JSON (REST) ​​на поддомене B с использованием защиты CORS и CSRF

1
Visionscaper

Если ваши куки настроены на запрет доступа к JavaScript, вам нужно сделать следующее. В своем шаблоне перед созданием приложения Django добавьте:

<script>
    window.csrf_token = "{{ csrf_token }}";
</script>

В своем угловом приложении добавьте это: 

angularApp.config(["$httpProvider", function($httpProvider) {
    $httpProvider.defaults.headers.common["X-CSRFToken"] = window.csrf_token;
}]);

По крайней мере, через Django 1.9 токен CSRF не меняется с каждым запросом. Он изменяется только при входе пользователя в систему. Если вы работаете с одностраничным угловым приложением, вам необходимо убедиться, что вы сбросили токен при входе/выходе, и это должно работать нормально.

ПРИМЕЧАНИЕ. В настоящее время это не работает в Django 1.10 или более поздней версии из-за изменения токена CSRF при каждом запросе. Смотрите Передайте токен Django CSRF в Angular с помощью CSRF_COOKIE_HTTPONLY

0
Zags