我正在尝试为Django设置测试一个在开发模式下运行良好的部署配置。
我通过负载均衡器上的Nginx的ssl_preread
模块进行了基于名称的路由,SSL终止于服务器本身上的另一个Nginx实例,在该实例中,请求通过套接字代理到uwsgi。
server {
server_name dev.domain.net;
listen 80 proxy_protocol;
listen [::]:80 proxy_protocol;
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name dev.domain.net;
listen 443 ssl;
listen [::]:443 ssl;
location / {
include uwsgi_params;
uwsgi_pass unix:/run/uwsgi/website.sock;
}
location /favicon.ico {
access_log off; log_not_found off;
}
}
我将uwsgi设置为日志%(host)
和%(referer)
,它们在日志中匹配。
在我的uwsgi_params中,我像这样传递$host
和$referer
,因为我使用基于名称的路由,所以我选择了触发Nginx响应的$server_name
变量。。。
uwsgi_param HTTP_REFERER $server_name;
uwsgi_param HTTP_HOST $host;
添加(或删除(协议和端口并没有什么区别。可以预见地,将它们拿走会生成DjangoALLOWED_HOSTS
调试错误。
我已经确认我的ALLOWED_HOSTS
包括$host
。我已经尝试为相同的$host
变量添加CSRF_TRUSTED_ORIGINS
。我已经尝试为相同的$host
变量设置CSRF_COOKIE_DOMAIN
。根据文档建议,我已将CSRF_COOKIE_SECURE
设置为True。
无论使用上述设置的哪种组合,我都会得到:
Referer checking failed - Referer is malformed.
处理所有POST请求。
简短的回答:不要使用uwsgi-unix套接字,而是使用http-socket
并通过未加密的http(在uwsgi-ini文件中(向localhost发送代理请求:
http-socket = 127.0.0.1:8001
在nginx中,去掉uwsgi代理参数,只需启用proxy_protocol
头的proxy_pass
:
server {
server_name dev.domain.net;
listen 443 ssl proxy_protocol;
listen [::]:443 ssl proxy_protocol;
location / {
proxy_pass http://127.0.0.1:8001;
}
location /favicon.ico {
access_log off; log_not_found off;
}
}
此时,您可以在Django文档中启用所有推荐的部署设置,显式声明ALLOWED_HOSTS
,一切正常。
这是一系列非常愚蠢的问题,没有一套明显正确的答案,尤其是考虑到裁判是很容易伪造的客户端标题。
更好的答案是Django需要在其CSRF机制中取消客户端-裁判检查,这毫无意义。。。