У меня есть django, работающий на сервере apache с использованием mod_wsgi, а также приложение angularjs, которое выполняется непосредственно apache, а не django. Я хотел бы сделать POST-вызовы на сервер django (работает rest_framework), но у меня возникают проблемы с токеном csrf.
Можно ли установить маркер с сервера, не помещая {% csrf token %}
в качестве части шаблона (поскольку эти страницы не проходят через django)?
- Я хотел бы иметь возможность получить токен csrf через запрос GET в качестве файла cookie.
- Я хотел бы иметь возможность затем отправлять POST-запросы на сервер django с использованием значения cookie файла маркера csrf.
Ответ 1
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() - это хорошее место для этого.
Что это.
ПРИМЕЧАНИЕ. Это для angular 1.1.5, более старым версиям может потребоваться другой подход.
Обновление:
Так как приложение angular не обслуживается django, чтобы позволить cookie быть установленным, приложение angular должно сначала выполнить запрос GET для django.
Ответ 2
var foo = angular.module('foo', ['bar']);
foo.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
И все модули и контроллеры, в которых используется $http, будут отправлять запросы с помощью токена csrf.
Ответ 3
После поиска, что сработало для меня, был этот пост со следующим кодом:
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');
})
Это, конечно, после получения файла cookie через запрос GET с сервера django.
Я также рассмотрел некоторые другие ответы здесь, в том числе Е. Люн, но не смог найти ничего в официальных документах, определяющих изменения параметров по умолчанию для xsrf на $httpProvider, кроме этот запрос на растяжение, который не работал у меня во время написания этого сообщения.
Ответ 4
Я создал приложение Django для моего приложения AngularJS, в том же проекте Django, что и приложение Django для моего (REST) API, которое обслуживает только файл index.html(который является только sym.link). Таким образом, CSRF Cookie устанавливается без дополнительного запроса GET.
Пожалуйста, см. мой ответ здесь Единичное веб-приложение AngularJS на субдомене. Разговор с API Jango JSON (REST) в поддомене B с использованием защиты CORS и CSRF.
Ответ 5
Если у вас есть файлы cookie, запрещающие доступ к javascript, вам необходимо сделать следующее. В своем шаблоне перед созданием приложения django добавьте следующее:
<script>
window.csrf_token = "{{ csrf_token }}";
</script>
В вашем приложении angular добавьте следующее:
angularApp.config(["$httpProvider", function($httpProvider) {
$httpProvider.defaults.headers.common["X-CSRFToken"] = window.csrf_token;
}]);
Как минимум через Django 1.9, токен CSRF не изменяется с каждым запросом. Он изменяется только при входе пользователя в систему. Если вы используете одностраничное приложение angular, вам нужно убедиться, что вы reset токен при входе/выходе из системы, и это должно работать нормально.
ПРИМЕЧАНИЕ. Это не работает в Django 1.10 или новее из-за изменения токена CSRF для каждого запроса. См. Пропустить токен CSRF для Django до angular с помощью CSRF_COOKIE_HTTPONLY