Django CSRF“Referer Malformed"......但它不是 [英] Django CSRF "Referer Malformed"... but it isn't
问题描述
我正在尝试测试在开发模式下运行良好的 Django 设置的部署配置.
I'm trying to test a deployment config for a Django setup that works fine in development mode.
我通过负载均衡器上的 Nginx 的 ssl_preread
模块进行基于名称的路由,并且 SSL 在服务器本身的另一个 Nginx 实例处终止,其中请求通过套接字代理到 uwsgi.
I have name-based routing via Nginx's ssl_preread
module on a load balancer, and SSL terminates at another Nginx instance on the server itself where the requests are proxied to uwsgi by socket.
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)
,它们在日志中匹配.
I have uwsgi set to log %(host)
and %(referer)
, they match in the logs.
在我的 uwsgi_params 中,我像这样传递 $host
和 $referer
,因为我使用的是基于名称的路由,所以我选择了 $server_name
触发 Nginx 响应的变量...
In my uwsgi_params I'm passing $host
and $referer
like so, since I'm using name-based routing I pick up the $server_name
variable that triggered the Nginx response...
uwsgi_param HTTP_REFERER $server_name;
uwsgi_param HTTP_HOST $host;
向这些添加(或删除)协议和端口没有区别.可预见地将它们带走会产生 Django ALLOWED_HOSTS
调试错误.
Adding (or taking away) protocols and ports to these makes no difference. Taking them away predictably generates a Django ALLOWED_HOSTS
debug error.
我已确认我的 ALLOWED_HOSTS
包含 $host
.我尝试为相同的 $host
变量添加 CSRF_TRUSTED_ORIGINS
.我尝试为相同的 $host
变量设置 CSRF_COOKIE_DOMAIN
.根据文档建议,我将 CSRF_COOKIE_SECURE
设置为 True.
I've confirmed that my ALLOWED_HOSTS
includes the $host
. I've tried adding CSRF_TRUSTED_ORIGINS
for the same $host
variable. I've tried setting CSRF_COOKIE_DOMAIN
for the same $host
variable. I have CSRF_COOKIE_SECURE
set to True per the docs recommendation.
无论使用上述设置的哪种组合,我都得到:
No matter what combination of the above settings are used, I get:
Referer 检查失败 - Referer 格式错误.
在所有 POST 请求中.
Referer checking failed - Referer is malformed.
on all POST requests.
推荐答案
Short answer: 不要使用 uwsgi unix socket,而是使用 http-socket
并将代理请求发送到 localhost未加密的 http(在 uwsgi ini 文件中):
Short answer: don't use the uwsgi unix socket, but rather use http-socket
and send the proxy request to localhost over unencrypted http (in uwsgi ini file):
http-socket = 127.0.0.1:8001
在 nginx 中,去掉 uwsgi 代理参数,并简单地在 proxy_pass
启用 proxy_protocol
标头:
In nginx, get rid of uwsgi proxy params and simply proxy_pass
with proxy_protocol
headers enabled:
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
并且一切正常.
At that point you can enable all of the recommended deployment settings in the Django docs, explicitly declare your ALLOWED_HOSTS
and everything works fine.
这些是一系列非常愚蠢的圈套,没有明显正确的答案集,特别是考虑到引用是很容易伪造的客户端标头.
These are a quite silly series of hoops with no apparent correct set of answers, especially considering referers are client headers that are easily forged.
更好的答案是 Django 需要在其 CSRF 机制中摆脱客户端引用检查,它毫无意义且毫无意义......
The better answer is Django needs to get rid of a client referer check in its CSRF mechanism, it's pointless and makes no sense...
这篇关于Django CSRF“Referer Malformed"......但它不是的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!