Подтвердить что ты не робот

Ошибка JSRO REST Framework CSRF: cookie CSRF не установлен

Я использую среду django rest для выполнения вызовов API через IOS и я получаю следующую ошибку "CSRF Failed: CSRF cookie не установлен".

Здесь мой код API django:

class LoginView(APIView):
    """
    List all snippets, or create a new snippet.
    """
    @csrf_exempt
    def get(self, request, format=None):
        startups = Startup.objects.all()
        serializer = StartupSerializer(startups, many=True)
        return Response(serializer.data)

    @csrf_exempt
    def post(self, request, format=None):
        profile = request.POST
....

Что я могу сделать?

4b9b3361

Ответ 1

Если кто-то все еще следует этому вопросу, прямой ответ заключается в том, что вам нужно использовать декоратор для самого метода представления. Методы get и post, определенные в классе APIView, просто указывают DRF, как должен выглядеть фактический вид, но метод представления, который ожидает маршрутизатор django, фактически не создается, пока вы не вызовете LoginView.as_view().

Таким образом, решение заключается в добавлении декоратора csrf_exempt к urls.py. Он может выглядеть следующим образом:

#file: urls.py

from django.conf.urls import patterns, url
from django.views.decorators.csrf import csrf_exempt

import views

urlpatterns = patterns('',
    url('^login/$', csrf_exempt(views.LoginView.as_view())),
    ...
)

Однако, как указывает Марк, защита csrf важна для предотвращения захвата ваших сессий. Я сам не работал с iOS, но я бы рассмотрел использование django токенов csrf на основе файлов cookie. Вы можете использовать декоратор ensure_csrf_cookie, чтобы django отправил cookie csrftoken с ответом, и ваши запросы post будут проверяться до тех пор, пока вы включите этот токен в заголовок X-CSRFToken.

Ответ 2

Для GET вы не должны изменять данные, поэтому CSRF не требуется.

Если вы изменяете данные с помощью POST, тогда вы должны иметь CSRF, если используете аутентификацию на основе сеанса. В противном случае вы откроете отверстие для безопасности. Несмотря на то, что вы думаете, что ваш сервер Django будет обслуживать приложения для iPhone, ничто не мешает кому-то с вашим приложением обнюхивать пакеты на трафике на ваш сервер, а затем обращать инженерный доступ к серверу с другими типами веб-клиентов. По этой причине Django Rest Framework требует CSRF в некоторых случаях. Это упоминается в документации Django rest framework.

Путь к этому требованию для POST заключается в том, чтобы не использовать аутентификацию сеанса. Например, вы можете использовать BasicAuthentication через HTTPS. С помощью этого механизма аутентификации вы должны использовать HTTPS для предотвращения передачи учетных данных в ящике с каждым запросом.

Ответ 3

Проблема, с которой вы сталкиваетесь, заключается в том, что django для обработки вашего представления использует любой метод as_view(), а не метод get() или post().

Поэтому вы должны украсить свой класс-представление одним из следующих способов:

  • В urls.py
    urlpatterns = patterns('',
        url('^login/$', csrf_exempt(views.LoginView.as_view())),
        ...
    )
  1. или по методу dispatch() (pre django 1.9)
    from django.utils.decorators import method_decorator

    class LoginView(APIView):
       @method_decorator(csrf_exempt)
       def dispatch(self, *args, **kwargs):
           ...
  1. или в самом представлении класса (из django 1.9)
    from django.utils.decorators import method_decorator


    @method_decorator(csrf_exempt, name='dispatch')
    class LoginView(APIView):
           ...

Ответ 4

Это старый вопрос, но что-то, с чем мы столкнулись в последнее время.

DRF отключает CSRF по умолчанию, если не используется аутентификация сеанса. По умолчанию NSURLconnection настроен для обработки файлов cookie. Вам нужно явно указать приложение iOS не использовать файлы cookie. Затем вы можете продолжать использовать сессию auth, если это необходимо, и не должны csrf освобождать ваши представления.

Ответ 5

У меня была такая же проблема. Моя проблема заключалась в том, что я забыл, но .as_view() в urls.py на MyAPIView. Поэтому это должно быть похоже:

url(r'$', GetLikesAPI.as_view(), name='list')

not:

url(r'$', GetLikesAPI, name='list')

Ответ 6

В моем случае это произошло потому, что я отправил запрос запроса url = 'http://example.com/list/5' без косой черты в конце. Когда я изменил url на url = 'http://example.com/list/5/' все начали работать.