X-Forwarded-Proto与Flask
我遇到的问题和这个StackOverflow上的问题一模一样。那里的回答提供了一个不错的解决方法,但我不太明白根本的问题是什么。在负载均衡器上终止SSL(安全连接)并在负载均衡器和网页/应用服务器之间使用HTTP是很常见的做法。那么,哪个部分没有正确处理X-Forwarded-Proto这个信息呢?是werkzeug吗?Flask吗?还是uwsgi?
在我的情况中,我使用的是AWS的ELB(它会设置X-Forwarded-Proto) => Nginx(它会把X-Forwarded-Proto转发给uwsgi)。但是在我的Python应用中,我不得不像上面提到的问题那样去扩展Flask的请求类。
因为这是一个非常常见的部署场景,所以我觉得应该有更好的解决方案。我是不是漏掉了什么?
1 个回答
你缺少了一个叫做 ProxyFix()
的中间件组件。可以查看 Flask 的 Proxy 设置文档。
你不需要去继承什么东西,只需将这个中间件组件添加到你的 WSGI 堆栈中:
# Werkzeug 0.15 and newer
from werkzeug.middleware.proxy_fix import ProxyFix
from flask import Flask
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1)
如果你已经安装了 Flask,那你也有 Werkzeug,但要确保版本是 >=0.15,这样才能获取到更新的 ProxyFix
版本(Flask 1.1.0 及更新版本已经使用了这个版本)。
这个组件会 根据 X-Forwarded-Proto 头来设置 WSGI 的协议类型。建议你阅读我上面提到的 Flask 文档,了解如何信任头信息以及如何根据你的具体情况定制中间件。上面我配置的是只查看 X-Forwarded-Proto
,但这个组件也可以处理其他的 X-Forwarded-*
配置。
默认情况下,它会信任一层的 X-Forwarded-For
,如果你想禁用这个功能,可以在关键字参数中添加 x_for=0
。
另外要注意的是,ProxyFix
中间件的功能在 Werkzeug 0.15 中得到了很大的扩展;除了 X-Forwarded-Proto
、-For
和 -Host
,还会考虑 X-Forwarded-Port
和 -Prefix
头,所有头信息都支持多个值。