Col*_*phy 5 django ssl nginx csrf
我最近一直在开发 django 应用程序,它终于准备好部署到质量保证和生产环境中了。一切都在本地完美运行,但由于增加了现实世界部署的复杂性,我遇到了一些问题。
首先,我的技术堆栈有点复杂。对于部署,我使用 aws 进行所有操作,将我的站点部署在由负载均衡器支持的多个 ec2 上。负载均衡器使用 ssl 进行保护,但到负载均衡器的连接将通过端口 80 上的标准 http 转发到 ec2。在端口 80 上访问 ec2 后,它们将转发到端口 8000 上的 docker 容器(如果您不熟悉docker 只是认为它是一个标准的虚拟机)。在容器内部,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/;
}
}
Run Code Online (Sandbox Code Playgroud)
我使用 X-Forwarded 主机,因为我遇到了来自 google oauth 的重定向问题,并且重定向提示用户登录,使浏览器请求 url 127.0.0.1:8001,这显然不起作用。在我的 settings.py 文件中我还包括
USE_X_FORWARDED_HOST = True
Run Code Online (Sandbox Code Playgroud)
强制 django 使用正确的主机进行重定向。
现在,该网站的常规浏览工作正常,静态文件加载、重定向工作正常,并且该网站通过 ssl 进行保护。但问题是 CSRF 验证失败。
在提交表单时,我收到以下错误
引用检查失败 - https://qa-load-balancer.com/projects/new与https://qa-load-balancer.com:443/不匹配。
我真的不知道该怎么办,实际上是通过 stackoverflow 问题,到目前为止我一切都正常。
我不会使用 HTTP 代理,而是使用 Nginx 的内置功能与 uWSGI 进行通信。(如果您为 Nginx 和 uWSGI 使用单独的 Docker 容器,这仍然有效,因为通信是通过 TCP 完成的)
典型的配置(我的)如下所示:
location / {
uwsgi_pass http://127.0.0.1:8001;
include uwsgi_params;
}
Run Code Online (Sandbox Code Playgroud)
您必须--http从 uWSGI 调用中删除参数(或等效的配置文件)。
此外,在 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;
Run Code Online (Sandbox Code Playgroud)
相关文档:http://uwsgi-docs.readthedocs.org/en/latest/WSGIquickstart.html#putting-behind-a-full-webserver
对于无法使用 Nginx 内置功能的用户,根本原因如下:
Referer和Host匹配,除非您指定 a (请参阅此处CSRF_TRUSTED_ORIGINS的代码)REASON_BAD_REFERER 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_NAMEproxy_set_header X-Forwarded-Host $host:$server_port;<host>进行比较。这些不匹配,因此 CSRF 失败。X-Forwarded-Host<host>:<port>关于这一点没有太多讨论,但 Django 票证#26037引用了RFC2616。该票证指出,没有端口的主机“违反规范”,但事实并非如此,因为规范实际上是这样说的:
没有任何尾随端口信息的“主机”意味着所请求服务的默认端口
这(至少)导致以下选项(最安全的第一):
CSRF_TRUSTED_ORIGINSport从nginx 配置中删除X-Forwarded-Host(假设非规范X-Forwarded-Host遵循与 相同的语义Host)为了避免对 中的域进行硬编码CSRF_TRUSTED_ORIGINS,第二个选项很有吸引力,但它可能会带来安全警告。推测:
X-Forwarded-Proto应用于阐明协议(因为缺少端口意味着默认协议)X-Forwarded-Proto可能会修复此问题)。| 归档时间: |
|
| 查看次数: |
3925 次 |
| 最近记录: |