在 Flask+Heroku 上将 HTTP 重定向到 HTTPS
Posted
技术标签:
【中文标题】在 Flask+Heroku 上将 HTTP 重定向到 HTTPS【英文标题】:Redirect HTTP to HTTPS on Flask+Heroku 【发布时间】:2013-02-13 12:13:19 【问题描述】:当我尝试将传入流量重定向到 https 时,我得到一个无限重定向循环。
@app.route('/checkout/')
def checkout():
checkout = "https://myapp.herokuapp.com/checkout/"
if checkout != request.url:
print checkout, request.url
return redirect(checkout)
return render_template('checkout.html', key=keys['publishable_key'])
request.url 永远不会更改为 https 前缀。我想使用 heroku 的背驮式 ssl 来最小化成本。
【问题讨论】:
【参考方案1】:在 Heroku 上,SSL (https) 在到达您的应用程序之前就被终止了,因此您的应用程序永远不会真正看到 SSL 流量。要检查是否使用 https 发出请求,您必须检查 x-forwarded-proto
标头。更多信息在这里:How to make python on Heroku https only?
更新:为了您的使用,您应该只检查 request.url 中的“myapp.herokuapp.com/checkout/”;并验证标头是“https”
【讨论】:
谢谢朋友。我已经看过 flask-sslify 包。除了我使用自定义域和heroku的子域之外,这将满足我的需求。我只想将 SSL 放在一页上。不过谢谢你的文档,我会通读的。 您应该只检查request.url
中的“myapp.herokuapp.com/checkout”并验证标头是否为“https”
谢谢,就是这样。
我已在答案中添加了评论 - 请考虑接受答案。
我会认真考虑 :) 如果您在回答中提到 flask-sslify,我会更加重视。【参考方案2】:
我能够将 flask-sslify 代码重新用于单个视图。只需要检查是否使用 SSL 发出请求并将正确的标头添加到响应中。 https://github.com/kennethreitz/flask-sslify
@app.route('/checkout/')
def checkout():
checkout = "https://myapp.herokuapp.com/checkout/"
if request.headers.get('X-Forwarded-Proto', 'http') == 'https':
resp = make_response(render_template('checkout.html', key=keys['publishable_key']))
return set_hsts_header(resp)
return redirect(checkout, code=302)
def set_hsts_header(response):
"""Adds HSTS header to each response."""
response.headers.setdefault('Strict-Transport-Security', hsts_header)
return response
def hsts_header():
"""Returns the proper HSTS policy."""
hsts_policy = 'max-age=0'.format(31536000) #year in seconds
if self.hsts_include_subdomains:
hsts_policy += '; includeSubDomains'
return hsts_policy
【讨论】:
【参考方案3】:1) 执行“pip install flask-sslify”
(github在这里:https://github.com/kennethreitz/flask-sslify)
2) 包括以下几行:
from flask_sslify import SSLify
if 'DYNO' in os.environ: # only trigger SSLify if the app is running on Heroku
sslify = SSLify(app)
【讨论】:
'DYNO' in os.environ
提示特别有用。【参考方案4】:
我尝试了 SSLify、url_for _scheme,并设置了 PREFERRED_URL_SCHEME;但是没有一个成功,至少在发布级别..(在本地工作得很好)然后我想;
@app.before_request
def beforeRequest():
if not request.url.startswith('https'):
return redirect(request.url.replace('http', 'https', 1))
这本质上是另一种无需任何配置或扩展即可完成的方法。
【讨论】:
这导致我“这个网页有一个重定向循环” @tdc 有趣,在有人编辑此答案之前,您是否尝试过我给出的答案?我没有试过这个,虽然它看起来应该是一样的;我知道原版肯定效果很好。 我没看过原版! SSLify 最终为我工作【参考方案5】:您只需要检查X-Forwarded-Proto
标头。如果为 false,则重定向到等效的 https url。
这里是对运行在 heroku 上的烧瓶应用程序的所有调用强制执行 https 的代码:
@app.before_request
def enforceHttpsInHeroku():
if request.headers.get('X-Forwarded-Proto') == 'http':
url = request.url.replace('http://', 'https://', 1)
code = 301
return redirect(url, code=code)
【讨论】:
【参考方案6】:你可以这样做:
@app.before_request
def before_request():
if 'DYNO' in os.environ: # Only runs when on heroku
if request.url.startswith('http://'):
url = request.url.replace('http://', 'https://', 1)
code = 301
return redirect(url, code=code)
【讨论】:
【参考方案7】:在我对another question 的回答中,我已经说明了最新的 Flask 建议。使用 Talisman 代替 SSLify。
对于 Flask,请使用 Talisman。 Flask、Heroku 和 SSLify 文档倾向于使用Talisman 而不是 SSLify,因为 后来不再维护。
来自SSLify:
不再维护扩展,更喜欢使用 Flask-Talisman 作为 Flask 安全指南鼓励这样做。
通过 pip 安装:
$ pip install flask-talisman
实例化扩展(示例):
from flask import Flask from flask_talisman import Talisman app = Flask(__name__) if 'DYNO' in os.environ: Talisman(app)
Talisman 默认仅启用 CSP(内容安全策略) 允许加载来自同一域的资源。如果你想 禁用它并处理其影响:
Talisman(app, content_security_policy=None)
如果您不想禁用它,您已设置
content_security_policy
参数允许来自外部的资源 域,例如 CDN。为此,请参阅 documentation.
【讨论】:
以上是关于在 Flask+Heroku 上将 HTTP 重定向到 HTTPS的主要内容,如果未能解决你的问题,请参考以下文章
Heroku:Python Flask 应用程序 - 自动从 https 重定向到 http
如何在 Mongoose 上将 MongoDB 连接到 Heroku?
Flask-SocketIO - WebSocket 在连接建立之前关闭。 [Heroku]