Django 在本地 Nginx 代理后面返回 "CSRF verification failed. Request aborted. "
Django returning "CSRF verification failed. Request aborted. " behind Nginx proxy locally
我是 运行 一个简单的 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 容器中设置 let's encrypt 后在服务器上运行没有任何问题,但在本地我收到“CSRF 验证失败。请求已中止。”每次提交表单时都会出错(例如,在 Django Admin 中创建一个虚拟用户)。我公开了 Web 端口并用它来提交表单并且它起作用了。
因此,我推断 Nginx 配置中缺少某些东西或“告诉”Django 如何处理它的东西。那么,我缺少什么以及我应该如何调查它?
由于您使用的是将 https 请求转换为 http 的代理,因此您需要将 Django 配置为允许来自不同方案 (since Django 4.0) 的 POST 请求,方法是将其添加到 [=11] =]:
CSRF_TRUSTED_ORIGINS = ["https://yourdomain.com", "https://www.yourdomain.com"]
如果这不能解决您的问题,您可以在生产中暂时设置DEBUG = True
并重试。在错误页面上,您会看到“给出的失败原因”,您可以在此处post。
我是 运行 一个简单的 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 容器中设置 let's encrypt 后在服务器上运行没有任何问题,但在本地我收到“CSRF 验证失败。请求已中止。”每次提交表单时都会出错(例如,在 Django Admin 中创建一个虚拟用户)。我公开了 Web 端口并用它来提交表单并且它起作用了。
因此,我推断 Nginx 配置中缺少某些东西或“告诉”Django 如何处理它的东西。那么,我缺少什么以及我应该如何调查它?
由于您使用的是将 https 请求转换为 http 的代理,因此您需要将 Django 配置为允许来自不同方案 (since Django 4.0) 的 POST 请求,方法是将其添加到 [=11] =]:
CSRF_TRUSTED_ORIGINS = ["https://yourdomain.com", "https://www.yourdomain.com"]
如果这不能解决您的问题,您可以在生产中暂时设置DEBUG = True
并重试。在错误页面上,您会看到“给出的失败原因”,您可以在此处post。