我正在使用url_for
在用户注销时生成重定向网址:
return redirect(url_for('.index', _external=True))
但是,当我将页面更改为 https 连接时,url_for
仍然提供 http 。
我想明确要求url_for
在网址开头添加 https 。
你能指点我怎么改变吗?我看着Flask的文档,没有运气。
答案 0 :(得分:48)
使用Flask 0.10,可以获得比包裹url_for
更好的解决方案。如果您查看https://github.com/mitsuhiko/flask/commit/b5069d07a24a3c3a54fb056aa6f4076a0e7088c7,则会添加_scheme
参数。这意味着您可以执行以下操作:
url_for('secure_thingy',
_external=True,
_scheme='https',
viewarg1=1, ...)
_scheme
设置网址方案,生成类似https://..
而非http://
的网址。但是,默认情况下,Flask仅生成路径(没有主机或方案),因此您需要包含从_external=True
到/secure_thingy
的{{1}}。
但是,请考虑将您的网站设为仅限HTTPS。您似乎只是尝试为少数“安全”路由部分强制执行HTTPS,但无法确保您的https如果链接到安全页面的页面未加密,则不会更改-URL。这类似于mixed content。
答案 1 :(得分:25)
如果您想影响所有服务器生成的网址(redirect
和_scheme
)的网址方案,而不是必须在每次通话时设置environ['wsgi.url_scheme'] = 'https'
,那么似乎“正确的“答案是使用WSGI中间件,如本摘录中所述:get output from a paramiko ssh exec_command continuously
(http://flask.pocoo.org/snippets/35/似乎证实这是首选方式。)
基本上,如果您的WSGI环境有url_for
,则https:
会生成http://
个网址。
我从url_for
获取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与服务器通信。我的解决方案(特定于Elastic Beanstalk)就像这样(从上面链接的片段中简化):
HTTP_X_FORWARDED_PROTO
特定于Elastic Beanstalk的部分是environ['wsgi.url_scheme'] = 'https'
。其他环境可以通过其他方式确定外部URL是否包含https。如果您只想使用HTTPS,则可以无条件地设置PREFERRED_URL_SCHEME
。
SELECT categorias.categoria_nombre
,categorias.seccion
,tipo_item.nombre
,tipo_item.detalle
,items.codigo_barra
FROM categorias
INNER JOIN tipo_item ON (
categorias.id = tipo_item.categoria
AND categorias.secion = '$dato'
AND categorias.categoria_nombre = '$dato_extra'
)
INNER JOIN items ON (
tipo_item.id = items.tipo_item
AND $ESTADO
) LIMIT 100 OFFSET $offset
不是这样做的方法。这是This Flask bug。
答案 2 :(得分:23)
我使用url_for
arg尝试了接受的答案,但我发现使用PREFERRED_URL_SCHEME
配置变量并将其设置为https更容易:
app.config.update(dict(
PREFERRED_URL_SCHEME = 'https'
))
因为您不必将其添加到每个url_for
来电。
答案 3 :(得分:11)
如果您通过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
答案 4 :(得分:8)
在每次_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)
答案 5 :(得分:1)
对于最近在这里结束的任何人,有一个官方的uwsgi修复程序用于此操作: https://stackoverflow.com/a/23504684/13777925
FWIW对于我来说仍然不起作用,因为标头设置不正确,所以我对ReversedProxied中间件进行了扩充,使其更倾向于使用https:
class ReverseProxied(object):
"""
Because we are reverse proxied from an aws load balancer
use environ/config to signal https
since flask ignores preferred_url_scheme in url_for calls
"""
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
# if one of x_forwarded or preferred_url is https, prefer it.
forwarded_scheme = environ.get("HTTP_X_FORWARDED_PROTO", None)
preferred_scheme = app.config.get("PREFERRED_URL_SCHEME", None)
if "https" in [forwarded_scheme, preferred_scheme]:
environ["wsgi.url_scheme"] = "https"
return self.app(environ, start_response)
称为:
app = flask.Flask(__name__)
app.wsgi_app = ReverseProxied(app.wsgi_app)
通过这种方式,如果您明确设置了环境变量“ PREFERRED_URL_SCHEME”,或者如果nginx / etc / proxy设置了X_FORWARDED_PROTO,它将做正确的事。
答案 6 :(得分:0)
我个人无法通过此处的任何答案解决此问题,但发现只需将 --cert=adhoc
添加到flask run 命令的末尾,使flask 应用程序使用https 运行即可解决问题。< /p>
flask run --host=0.0.0.0 --cert=adhoc