Django DRF - ручная проверка маркера CSRF

Я прочитал в документации, что DRF проверяет CSRF-токены только на аутентифицированных запросах, а представления при входе должны явно проверять CSRF-токен.

Проблема в том, как вручную проверить CSRF-токен?

В моем settings.py:

MIDDLEWARE = [
    ...
    "django.middleware.csrf.CsrfViewMiddleware",
    ...
]

Вот мое мнение:

from rest_framework.decorators import api_view
from django.http import JsonResponse
from django.views.decorators.csrf import get_token


# I have to manually generate the csrf token and put it in the response body, because I use react-native and that can't read the token from the 'Set-Cookie' header
@api_view(["GET"])
def user_info(request):
    return JsonResponse({"csrf_token": get_token(request)})


@api_view(["POST"])
def login(request):
    return JsonResponse({"foo": "bar"})

Когда я делаю POST-запрос во фронтенде и не предоставляю CSRF-токен, он должен завершиться неудачей, но на самом деле я получаю {"foo": "bar"} JSON.

Я попробовал декораторы @csrf_protect и @requires_csrf_token, но запрос по-прежнему не проходит.

Я также пробовал это, но ошибка на required positional argument: 'get_response

CsrfViewMiddleware().process_view(request, None, (), {})

Если я передаю функцию в get_response, эта функция никогда не вызывается:

def test_get_response(req):
    breakpoint()

CsrfViewMiddleware(get_response=test_get_response).process_request(request)

Я проверил, что CSRF-токен не передается в заголовках, а не в куках, и я пробовал разные браузеры и режим инкогнито.

Как заставить мои api запросы не работать, если они не включают действительный CSRF токен?

У вас ошибка в этом импорте from django.views.decorators.csrf import get_token . вы должны импортировать get_token из django.middleware.csrf . согласно документации django и он вернет CSRF токен, необходимый для POST формы.

Ладно... через несколько кроличьих нор я нашел какое-то решение.

Django использует Double Submit Cookie для проверки CSRF. Это означает:

  1. Фронтенд запрашивает CSRF-токен у Django
  2. .
  3. Django генерирует токен, отправляет его FE в заголовке Set-Cookie
  4. FE помещает csrf в cookie, который не может быть изменен потенциальным злоумышленником
  5. FE помещает тот же токен в POST форму и отправляет ее в Django
  6. .
  7. Django проверяет, совпадают ли токен в POST форме и cookie
  8. .

Проблема в том, что React Native не поддерживает cookies, поэтому приходится отправлять CSRF-токен другим способом. Проблема в том, что нет способа сделать это безопасно.

Я решил эту проблему, написав пользовательское промежуточное ПО для django:

  1. FE запрашивает CSRF-токен у Django
  2. Django генерирует токен, отправляет его FE, И сохраняет хэшированную версию в базе данных
  3. FE помещает его в POST форму и отправляет в Django
  4. Django хэширует токен, проверяет, есть ли хэш в db
  5. .
  6. После успешной валидации Django удаляет токен из базы данных
  7. .
  8. Задание CRON удаляет все неиспользованные токены через 24 часа

Немного громоздко, но мне приходится проверять таким образом только веб-запросы.

Вернуться на верх