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 и попробовать снова. На странице ошибки вы увидите "Причину неудачи", которую вы можете опубликовать здесь.

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