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.