Django 在本地 Nginx 代理后面返回“CSRF 验证失败。请求中止。”

问题描述 投票:0回答:2

我正在运行一个简单的 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/;
    }

}

在 Nginx 容器中设置让我们加密后在服务器上运行它没有任何问题,但在本地我收到“CSRF 验证失败。请求中止”。每次我提交表单时都会出错(例如在 Django Admin 中创建一个虚拟用户)。我公开了网络端口并用它来提交表单并且它起作用了。

因此,我推断 Nginx 配置中缺少某些内容或“告诉”Django 如何处理它的内容。那么,我缺少什么以及我应该如何调查这个问题?

django nginx reverse-proxy
2个回答
28
投票

由于您使用的代理将 https 请求转换为 http,因此您需要将 Django 配置为允许来自不同方案的 POST 请求(自 Django 4.0),方法是将其添加到

settings.py
:

CSRF_TRUSTED_ORIGINS = ["https://yourdomain.com", "https://www.yourdomain.com"]

如果这不能解决您的问题,您可以在生产中暂时设置

DEBUG = True
,然后重试。在错误页面上,您将看到“失败原因”,您可以在此处发布。


0
投票

如果您使用 Nginx 作为反向代理,请确保它将 HTTP_REFERER 标头正确传递给 Django。您可能需要调整 Nginx 配置以允许 Referer 标头:

location / {
    proxy_set_header Referer $http_referer;
    ...
}
© www.soinside.com 2019 - 2024. All rights reserved.