[英]Redirect HTTP to HTTPS on Flask+Heroku
当我尝试将传入流量重定向到 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 的piggyback ssl 来最小化成本。
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)
在 Heroku 上,SSL (https) 在到达您的应用程序之前已终止,因此您的应用程序实际上从未看到 SSL 流量。 要检查请求是否是使用 https 发出的,您必须检查x-forwarded-proto
标头。 更多信息: How to make python on Heroku https only?
更新:对于您的使用,您应该只检查 request.url 的“myapp.herokuapp.com/checkout/”; 并验证标头是“https”
我尝试了 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))
这本质上是另一种无需任何配置或扩展即可完成的方法。
我能够将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
您只需要检查X-Forwarded-Proto
标头。 如果为 false,则重定向到等效的 https url。
这里是对运行在 heroku 上的 Flask 应用程序上的所有调用强制执行 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)
你可以这样做:
@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)
在我对另一个问题的回答中,我已经说明了最新的 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。 为此,请参阅文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.