Django REST Framework - токен CSRF отсутствует в представлении API для входа в систему [duplicate]

Взгляд на разборку может прояснить, что происходит:

>>> def f():
...    print a
...    print b
...    a = 1

>>> import dis
>>> dis.dis(f)

  2           0 LOAD_FAST                0 (a)
              3 PRINT_ITEM
              4 PRINT_NEWLINE

  3           5 LOAD_GLOBAL              0 (b)
              8 PRINT_ITEM
              9 PRINT_NEWLINE

  4          10 LOAD_CONST               1 (1)
             13 STORE_FAST               0 (a)
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE

Как вы можете видеть, байт-код для доступа к a есть LOAD_FAST, а для b, LOAD_GLOBAL. Это связано с тем, что компилятор идентифицировал, что a назначается внутри функции, и классифицирует его как локальную переменную. Механизм доступа для местных жителей принципиально отличается для глобальных переменных - им статически присваивается смещение в таблице переменных фрейма, что означает, что поиск является быстрым индексом, а не более дорогим исканием dict, как для глобальных. Из-за этого Python считывает строку print a как «получает значение локальной переменной« a », содержащееся в слоте 0, и печатает его», и когда он обнаруживает, что эта переменная все еще не инициализирована, возникает исключение.

71
задан Irene Texas 16 June 2015 в 14:49
поделиться

9 ответов

Почему эта ошибка происходит?

Это происходит из-за схемы SessionAuthentication по умолчанию, используемой DRF. DRF SessionAuthentication использует среду сеансов Django для аутентификации, которая требует проверки CSRF.

Если вы не определяете какой-либо authentication_classes в вашем представлении / просмотре, DRF использует эти классы проверки подлинности в качестве значения по умолчанию.

'DEFAULT_AUTHENTICATION_CLASSES'= (
    'rest_framework.authentication.SessionAuthentication',
    'rest_framework.authentication.BasicAuthentication'
),

Поскольку DRF необходимо поддерживать как сеанс, так и несинхронная аутентификация на одни и те же представления, она обеспечивает проверку CSRF только для аутентифицированных пользователей. Это означает, что только аутентифицированные запросы требуют токенов CSRF, а анонимные запросы могут быть отправлены без токенов CSRF.

Если вы используете API стиля AJAX с SessionAuthentication, вам нужно будет указать действительный токен CSRF для любого «небезопасные» вызовы HTTP-метода, например PUT, PATCH, POST or DELETE.

Что делать?

Теперь, чтобы отключить проверку csrf, вы можете создать собственный класс проверки подлинности CsrfExemptSessionAuthentication, который простирается от класса по умолчанию SessionAuthentication. В этом классе аутентификации мы переопределим проверку enforce_csrf(), которая происходила внутри фактического SessionAuthentication.

from rest_framework.authentication import SessionAuthentication, BasicAuthentication 

class CsrfExemptSessionAuthentication(SessionAuthentication):

    def enforce_csrf(self, request):
        return  # To not perform the csrf check previously happening

В вашем представлении вы можете определить authentication_classes следующим образом:

authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)

Это должно обрабатывать ошибку csrf.

134
ответ дан nnyby 21 August 2018 в 04:31
поделиться
  • 1
    Спасибо, отличный ответ. Там должен быть встроенный способ сделать это в restframework, но в настоящее время это лучшее решение, которое я нашел. – Omer 13 October 2015 в 14:06
  • 2
    Спасибо, это сработало! с Django 1.9 – neosergio 17 April 2016 в 21:01
  • 3
    Извините, возможно, я пропустил этот момент, но не угроза безопасности для обхода / отключения защиты csrf? – Paolo 5 February 2017 в 19:37
  • 4
    @Paolo OP необходимо отключить аутентификацию CSRF для конкретного API. Но да, это угроза безопасности для отключения защиты csrf. Если нужно отключить аутентификацию сеанса для конкретного варианта использования, то он может использовать это решение. – Rahul Gupta 6 February 2017 в 07:09
  • 5
    Hey @RahulGupta - Невозможно проверить, есть ли в представлении csrf_exempt decorator, а затем отключить принудительный_csrf для этих представлений? – Abhishek 30 March 2018 в 12:04

Более простое решение:

В views.py используйте скобки CsrfExemptMixin и authentication_classes:

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from django.views.decorators.csrf import csrf_exempt
from braces.views import CsrfExemptMixin


class Object(CsrfExemptMixin, APIView):
    authentication_classes = []

    def post(self, request, format=None):
        return Response({'received data': request.data})
7
ответ дан bixente57 21 August 2018 в 04:31
поделиться

Если вы не хотите использовать аутентификацию на основе сеанса, вы можете удалить Session Authentication из REST_AUTHENTICATION_CLASSES и автоматически удалить все проблемы на основе csrf. Но в этом случае Apache с возможностью просмотра может не работать.

Кроме того, эта ошибка не должна совпадать даже с аутентификацией сеанса. Вы должны использовать настраиваемую аутентификацию, такую ​​как TokenAuthentication для своего apis, и не забудьте отправить Accept:application/json и Content-Type:application/json (при условии, что вы используете json) в своих запросах вместе с токеном аутентификации.

6
ответ дан hspandher 21 August 2018 в 04:31
поделиться

Мое решение показано ударом. Просто украсьте мой класс.

from django.views.decorators.csrf import csrf_exempt
@method_decorator(csrf_exempt, name='dispatch')
@method_decorator(basic_auth_required(
    target_test=lambda request: not request.user.is_authenticated
), name='dispatch')
class GenPedigreeView(View):
    pass
0
ответ дан Jak Liao 21 August 2018 в 04:31
поделиться
  • 1
    Хотя этот код может ответить на вопрос, предоставляя дополнительный контекст относительно того, почему и / или как этот код отвечает на вопрос, улучшает его долгосрочную ценность. – Alex Riabov 31 July 2018 в 06:06

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

То, что вы наблюдали, происходит, потому что rest_framework/authentication.py имеет этот код в authenticate метод класса SessionAuthentication:

self.enforce_csrf(request)

Вы можете изменить класс Request, чтобы иметь свойство, называемое csrf_exempt, и инициализировать его внутри вашего соответствующего класса вида True, если вы не хотите Проверка CSRF. Например:

Затем измените приведенный выше код следующим образом:

if not request.csrf_exempt:
    self.enforce_csrf(request)

В классе Request есть некоторые связанные изменения. Полная реализация доступна здесь (с полным описанием): https://github.com/piaxis/django-rest-framework/commit/1bdb872bac5345202e2f58728d0e7fad70dfd7ed

0
ответ дан Reetesh Ranjan 21 August 2018 в 04:31
поделиться

Изменить urls.py

Если вы управляете своими маршрутами в urls.py, вы можете связать свои маршруты с помощью csrf_exempt (), чтобы исключить их из промежуточного программного обеспечения проверки CSRF.

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

urlpatterns = patterns('',
    url(r'^object/$', csrf_exempt(views.ObjectView.as_view())),
    ...
)

Альтернативно, в качестве декоратора Некоторые могут найти использование декоратора @csrf_exempt, более подходящего для их нужд

, например,

from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse

@csrf_exempt
def my_view(request):
    return HttpResponse('Hello world')

должен получить Job Done!

1
ответ дан Syed Faizan 21 August 2018 в 04:31
поделиться
  • 1
    Некоторое объяснение кода обеспечит лучший ответ. – chevybow 2 August 2018 в 17:58
  • 2
    @chevybow Really Извините, я на самом деле новичок в Сообществе. На самом деле его Decorator Django для отключения CSRF для определенного вида – Syed Faizan 2 August 2018 в 18:02
  • 3
    @chevybow Я обновил ответ, любезно посмотрю :) – Syed Faizan 2 August 2018 в 18:05

Для всех, кто не нашел полезного ответа. Да DRF автоматически удаляет CSRF-защиту, если вы не используете SessionAuthentication AUTHENTICATION CLASS, например, многие разработчики используют только JWT:

'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),

Но проблема CSRF not set может быть вызвана по другой причине, поскольку fm]

вместо

url(r'^api/signup/', CreateUserView.as_view()),
4
ответ дан user3479125 21 August 2018 в 04:31
поделиться

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

Добавить файл disable.py в одном из ваших приложений (в моем случае это «myapp»)

class DisableCSRF(object):
    def process_request(self, request):
        setattr(request, '_dont_enforce_csrf_checks', True)

И добавьте среднюю версию MIDDLEWARE_CLASSES

MIDDLEWARE_CLASSES = (
myapp.disable.DisableCSRF,
)
2
ответ дан Venkatesh Mondi 21 August 2018 в 04:31
поделиться
0
ответ дан chris Frisina 31 October 2018 в 23:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: