Получение ошибки отсутствия CSRF-токена на django rest framework (с TokenAuthentication) public APIView
У меня проблема с Django Rest Framework и конфигурациями CSRF. Я знаю, что есть много похожих постов на эту тему (например, этот Django Rest Framework remove csrf), но большинство из них не применимы (я не использую SessionAuthentication, ни шаблоны Django), и то, как DRF обрабатывает CSRF, все еще неясно для меня.
Вот ситуация :
- У меня есть приложение DRF, действующее как бэкенд API с несколькими маршрутами, с аутентификацией по токену (JWT) .
- У меня также есть отдельный фронтенд, взаимодействующий с моим API. Оба находятся на одном домене (скажем https://example.com и https://example.com/backend) .
- У меня есть простой
APIView
на стороне DRF для регистрации, на который мне нужно посылать POST запросы. Это представление не требует аутентификации.
Когда я отправляю POST-запрос, я получаю 403 Forbidden error
со следующим сообщением :
detail "CSRF Failed: CSRF token missing or incorrect."
Вот мое мнение:
class RecaptchaVerifyView(APIView):
permission_classes = []
serializer_class = ReCaptchaSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
return Response({'success': True}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Я читал, что DRF отключает CSRF, за исключением SessionAuthentication, которую я не использую. Я также читал, что пустой permission_classes
должен решить большинство проблем. Поэтому я думаю, что мне не нужно добавлять декоратор csrf_exempt
(который я все равно безуспешно пробовал, btw).
Объявление маршрута в urls.py
следующее:
urlpatterns = [
...
path('recaptcha_verify/', RecaptchaVerifyView.as_view(), name='recaptcha_verify'),
...
]
Наконец, некоторые соответствующие настройки django:
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
...
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
Также я не уверен, что делать с настройками, связанными с CSRF, такими как SESSION_COOKIE_HTTPONLY
, SESSION_COOKIE_SECURE
, CSRF_COOKIE_SECURE
, SESSION_COOKIE_NAME
, CSRF_COOKIE_NAME
, даже с самим CSRF middleware. Нужны они мне или нет
Из того, что я прочитал до сих пор, я думал, что мне не стоит беспокоиться о CSRF вообще, поскольку DRF применяет поведение Django по умолчанию, и я использую TokenAuthentication вместо SessionAuthentication.
Что я делаю не так?
P.S: У меня также есть другой публичный вид (страница входа), который работает нормально.
В настройке отсутствовала ключевая строка authentication_classes = ()
в дополнение к пустому списку permission_classes
.
Итак, мой класс APIView
теперь выглядит следующим образом :
class RecaptchaVerifyView(APIView):
permission_classes = ()
authentication_classes = ()
@swagger_auto_schema(responses={status.HTTP_200_OK: openapi.Response("")})
def post(self, request, *args, **kwargs):
serializer = ReCaptchaSerializer(data=request.data)
if serializer.is_valid():
return Response({'success': True}, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
И то же самое для представления регистрации. Потратил на это несколько часов, но теперь это имеет смысл, поскольку в документации DRF говорится, что без явного объявления authentication_classes
, по умолчанию применяется SessionAuthentication
, что требует CSRF токена.