Django CSRF "Referer Malformed" ...但事实并非如此



我正在尝试为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机制中取消客户端-裁判检查,这毫无意义。。。

相关内容

最新更新