Короткий ответ
Используется middleware django-cors-headers: добавляется в MIDDLEWARE, а разрешённые источники указываются в CORS_ALLOWED_ORIGINS; middleware добавляет заголовки Access-Control-Allow-Origin и обрабатывает preflight-запросы OPTIONS.
Как это работает подробнее
Браузер при межсайтовом запросе (другой origin: схема+домен+порт) сначала может отправить предварительный OPTIONS-запрос (preflight) для «небезопасных» методов/заголовков. Сервер должен ответить заголовками Access-Control-Allow-Origin, Access-Control-Allow-Methods и т. д., разрешающими конкретный origin; без этого браузер блокирует ответ на стороне клиента (сам запрос может даже выполниться на сервере, но JS не получит ответ).
Пример кода
example.py
# settings.py
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
]
CORS_ALLOWED_ORIGINS = [
"https://app.example.com",
]
# Проверка: запрос с Origin: https://app.example.com должен получить
# заголовок Access-Control-Allow-Origin: https://app.example.com в ответе,
# а запрос с другим Origin - не должен.Что использовать на практике
- Практика. В production указывают конкретные разрешённые домены (
CORS_ALLOWED_ORIGINS = ["https://app.example.com"]), а неCORS_ALLOW_ALL_ORIGINS = True, чтобы не открывать API для произвольных сайтов. Порядок middleware важен —corsheaders.middleware.CorsMiddlewareдолжен стоять доCommonMiddleware.
Подводные камни
- Риск. Путают CORS (ограничение браузера, не относится к серверной безопасности как таковой — не защищает от прямых запросов curl/postman) с полноценной аутентификацией/авторизацией; включают
CORS_ALLOW_ALL_ORIGINS«чтобы заработало» и забывают сузить в production.