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 только для этого приложения ?

767   9  

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. Но в этом случае просматриваемые API могут не работать.

кроме того, эта ошибка не должна приходить даже с проверкой подлинности сеанса. Вы должны использовать пользовательскую аутентификацию, например 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.

Comments

    Ничего не найдено.