当用户注销时,我使用url_for
生成重定向URL:
return redirect(url_for('.index', _external=True))
但是,当我将页面更改为https连接时,url_for
仍然给我http。
我想明确要求url_for
在URL的开头添加https。
你能指点我怎么改变它吗?我看着Flask的文档,没有运气。
使用Flask 0.10,可以获得比包裹url_for
更好的解决方案。如果你看一下https://github.com/mitsuhiko/flask/commit/b5069d07a24a3c3a54fb056aa6f4076a0e7088c7,就增加了一个_scheme
参数。这意味着您可以执行以下操作:
url_for('secure_thingy',
_external=True,
_scheme='https',
viewarg1=1, ...)
_scheme
设置URL方案,生成像https://..
而不是http://
的URL。但是,默认情况下,Flask只生成路径(没有主机或方案),因此您需要包含_external=True
以从/secure_thingy
转到https://example.com/secure_thingy
。
但是,请考虑将您的网站设为仅限HTTPS。您似乎只尝试为少数“安全”路由部分强制执行HTTPS,但如果链接到安全页面的页面未加密,则无法确保不更改您的https-URL。这类似于mixed content。
如果你想影响所有服务器生成的URL(url_for
和redirect
)的URL方案,而不是必须在每次调用时设置_scheme
,似乎“正确”的答案是使用WSGI中间件,如在此片段中:http://flask.pocoo.org/snippets/35/
(This Flask bug似乎证实这是首选方式。)
基本上,如果您的WSGI环境有environ['wsgi.url_scheme'] = 'https'
,那么url_for
将生成https:
URL。
我从http://
获取url_for
URL,因为我的服务器部署在Elastic Beanstalk负载均衡器后面,后者通过常规HTTP与服务器通信。我的解决方案(特定于Elastic Beanstalk)就像这样(从上面链接的代码段中简化):
class ReverseProxied(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
scheme = environ.get('HTTP_X_FORWARDED_PROTO')
if scheme:
environ['wsgi.url_scheme'] = scheme
return self.app(environ, start_response)
app = Flask(__name__)
app.wsgi_app = ReverseProxied(app.wsgi_app)
特定于Elastic Beanstalk的部分是HTTP_X_FORWARDED_PROTO
。其他环境可以通过其他方式确定外部URL是否包含https。如果您只想使用HTTPS,则可以无条件地设置environ['wsgi.url_scheme'] = 'https'
。
PREFERRED_URL_SCHEME
不是这样做的方式。这是ignored whenever a request is in progress。
我用url_for
arg尝试了接受的答案,但我发现使用PREFERRED_URL_SCHEME
配置变量更容易,并将其设置为https:
app.config.update(dict(
PREFERRED_URL_SCHEME = 'https'
))
因为你不必将它添加到每个url_for
调用。
如果您通过像Nginx这样的反向代理访问您的网站,那么Flask正确地将该方案视为HTTP
。
Browser -----HTTPS----> Reverse proxy -----HTTP----> Flask
最简单的解决方案是配置反向代理以设置X-Forwarded-Proto
标头。 Flask将自动检测此标头并相应地管理方案。有一个more detailed explanation in the Flask documentation under the Proxy Setups section。例如,如果使用Nginx,则必须在location
块中添加以下行。
proxy_set_header X-Forwarded-Proto $scheme;
正如其他提到的,如果您无法更改代理的配置,您可以使用werkzeug ProxyFix或构建您自己的修复程序,如文档中所述:http://flask.pocoo.org/docs/0.12/deploying/wsgi-standalone/#proxy-setups
在每个_scheme
电话上设置url_for()
是非常繁琐的,PREFERRED_URL_SCHEME
似乎不起作用。但是,如果请求的假设方案处于WSGI级别,则可能会成功说服Flask始终构建HTTPS URL:
def _force_https(app):
def wrapper(environ, start_response):
environ['wsgi.url_scheme'] = 'https'
return app(environ, start_response)
return wrapper
app = Flask(...)
app = _force_https(app)