Django Rest Framework удалить csrf

Я знаю, что есть ответы относительно Django Rest Framework, но я не мог найти решение своей проблемы.

у меня есть приложение, которое имеет аутентификацию и некоторые функции. Я добавил к нему новое приложение, которое использует Django Rest Framework. Я хочу использовать библиотеку только в этом приложении. Также я хочу сделать запрос POST, и я всегда получаю этот ответ:

{
    "detail": "CSRF Failed: CSRF token missing or incorrect."
}

у меня есть следующий код:

# urls.py
from django.conf.urls import patterns, url


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

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


class Object(APIView):

    @csrf_exempt
    def post(self, request, format=None):
        return Response({'received data': request.data})

Я хочу добавить API без влияет на текущее приложение. Итак, мои вопросы: как я могу отключить CSRF только для этого приложения ?

9 ответов


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

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

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

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

С ФПИ должен поддерживать оба сеанса и вне сеанса проверки подлинности на основе той же представления, он обеспечивает проверку 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.


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

In 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})

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

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


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

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

но проблема CSRF not set может произойти по какой-то другой причине, для примера вы неправильно добавили путь к вам:

url(r'^api/signup/', CreateUserView),  # <= error! DRF cant remove CSRF because it is not as_view that does it!

вместо

url(r'^api/signup/', CreateUserView.as_view()),

изменить 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')

должен получить работу!


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

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

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

и добавьте middileware в MIDDLEWARE_CLASSES

MIDDLEWARE_CLASSES = (
myapp.disable.DisableCSRF,
)

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

то, что вы наблюдали, происходит потому что 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


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

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

между изменениями DNS это также может быть фактором. Ожидание полного сброса DNS решит эту проблему, если она работала до проблем/изменений DNS.