我最近一直在研究django应用程序,它终于准备好部署到qa和生产环境了。一切都在本地完美运行,但由于增加了现实世界部署的复杂性,我遇到了一些问题。
首先我的技术堆栈有点复杂。对于部署,我使用aws来处理我的站点部署在由负载均衡器支持的多个ec2上的所有内容。负载均衡器使用ssl进行保护,但与负载均衡器的连接通过端口80上的标准http转发到ec2。在端口80上按下ec2后,它们将转发到端口8000上的docker容器(如果您不熟悉docker只是认为它是一个标准的vm)。在容器内部,nginx侦听端口8000,它处理django中静态文件的重定向,对于Web请求,它将请求转发到运行在127.0.0.1:8001上的django。 Django由uwsgi主持,侦听端口8001。
server {
listen 8000;
server_name localhost;
location /static/ {
alias /home/library/deploy/thelibrary/static/;
}
location / {
proxy_set_header X-Forwarded-Host $host:443;
proxy_pass http://127.0.0.1:8001/;
}
}
我使用X-Forwarded主机,因为我遇到了来自google oauth和重定向的重定向问题以提示用户登录,使浏览器请求URL 127.0.0.1:8001显然不起作用。在我的settings.py文件中,我还包括
USE_X_FORWARDED_HOST = True
强制django使用正确的主机进行重定向。
现在,网站的一般浏览工作完美,静态文件加载,重定向工作,网站使用ssl保护。但问题是CSRF验证失败。
在表单提交上,我收到以下错误
参与者检查失败 - https://qa-load-balancer.com/projects/new与https://qa-load-balancer.com:443/不匹配。
我真的不知道该怎么做,它真的是通过stackoverflow问题,到目前为止我已经完成了所有工作。
答案 0 :(得分:4)
我不会使用HTTP代理,而是使用Nginx的built-in capacity与uWSGI进行通信。 (如果您使用单独的Docker容器用于Nginx和uWSGI,因为通过TCP完成通信,这仍然有效)
典型配置(我的)如下所示:
location / {
uwsgi_pass http://127.0.0.1:8001;
include uwsgi_params;
}
您必须从uWSGI调用中删除--http
参数(或等效的配置文件)。
此外,在uwsgi_params(在/etc/nginx
中找到或您指定的自定义位置)中,有几个指令可以传递元数据。以下是我的摘录,看起来可能与您的问题有关:
...
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param HTTPS $https if_not_empty;
相关文档:http://uwsgi-docs.readthedocs.org/en/latest/WSGIquickstart.html#putting-behind-a-full-webserver
答案 1 :(得分:1)
对于不能使用Nginx内置工具的用户,这是根本原因:
Referer
和Host
匹配,除非您指定CSRF_TRUSTED_ORIGINS
(请参阅REASON_BAD_REFERER
周围的代码{{3} })CSRF_TRUSTED_ORIGINS
,系统将重新使用request.get_host()
request.get_host()
使用request._get_raw_host()
request._get_raw_host()
按顺序检查HTTP_X_FORWARDED_HOST
(如果设置了USE_X_FORWARDED_HOST
),HTTP_HOST
和SERVER_NAME
proxy_set_header X-Forwarded-Host $host:$server_port;
<host>
)与X-Forwarded-Host
进行比较(例如<host>:<port>
)。这些不匹配,因此CSRF失败。对此没有太多讨论,但Django票证here引用了#26037。该票证明没有端口的主机是“违规”,但这不符合规范实际上说:
没有任何尾随端口信息的“主机”意味着所请求服务的默认端口
这导致(至少)以下选项(最安全的第一个):
CSRF_TRUSTED_ORIGINS
port
删除X-Forwarded-Host
(假设非规范X-Forwarded-Host
遵循与Host
相同的语义)为了避免在CSRF_TRUSTED_ORIGINS
中对域进行硬编码,第二种选择很有吸引力,但它可能带有安全性警告。推测:
X-Forwarded-Proto
来阐明协议(因为没有端口意味着默认协议)X-Forwarded-Proto
可能会解决此问题。)