Django возвращает "Проверка CSRF не удалась. Запрос прерван. " за прокси Nginx локально
Я запускаю простое Django приложение без каких-либо сложных настроек (большинство по умолчанию, Django allauth & Django Rest Framework).
Инфраструктура для запуска как локально, так и удаленно находится в файле docker-compose:
version: "3"
services:
web:
image: web_app
build:
context: .
dockerfile: Dockerfile
command: gunicorn my_service.wsgi --reload --bind 0.0.0.0:80 --workers 3
env_file: .env
volumes:
- ./my_repo/:/app:z
depends_on:
- db
environment:
- DOCKER=1
nginx:
image: nginx_build
build:
context: nginx
dockerfile: Dockerfile
volumes:
- ./my_repo/:/app:z
ports:
- "7000:80"
... # db and so on
Как вы видите, я использую Gunicorn для обслуживания приложения и Nginx в качестве прокси (для статических файлов и настройки Let's Encrypt). Контейнер Nginx имеет некоторые настройки:
FROM nginx:1.21-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d
А файл nginx.conf - это обратный прокси со статическим отображением:
server {
listen 80;
location / {
proxy_pass http://web;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /static/ {
alias /app/my_repo/static/;
}
}
Запуск этого на сервере после настройки let's encrypt в контейнере Nginx работает без проблем, но локально я получаю ошибку "CSRF verification failed. Запрос прерван." каждый раз, когда я отправляю форму (например, создаю фиктивного пользователя в Django Admin). Я открыл веб-порт и использовал его для отправки форм, и все заработало.
Поэтому я делаю вывод, что в конфигурации Nginx чего-то не хватает или что-то "говорит" Django, как с этим работать. Итак, что я упускаю и как я должен это исследовать?
Поскольку вы используете прокси, который преобразует https запросы в http, вам нужно настроить Django на разрешение POST запросов с другой схемы ( начиная с Django 4.0), добавив это в settings.py
:
CSRF_TRUSTED_ORIGINS = ["https://yourdomain.com", "https://www.yourdomain.com"]
Если это не решит вашу проблему, вы можете временно установить DEBUG = True
в production и попробовать снова. На странице ошибки вы увидите "Причину неудачи", которую вы можете опубликовать здесь.