7

当我尝试将传入流量重定向到 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 来最小化成本。

4

7 回答 7

15

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)
于 2014-03-03T02:23:05.047 回答
7

在 Heroku 上,SSL (https) 在到达您的应用程序之前就被终止,因此您的应用程序永远不会真正看到 SSL 流量。要检查是否使用 https 发出请求,您必须检查x-forwarded-proto标头。更多信息:如何仅在 Heroku https 上制作 python?

更新:为了您的使用,您应该只检查 request.url 中的“myapp.herokuapp.com/checkout/”;并验证标头是“https”

于 2013-02-27T16:08:01.137 回答
6

我尝试了 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))

这本质上是另一种无需任何配置或扩展即可完成的方法。

于 2015-03-13T07:11:31.210 回答
0

我能够将 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 
于 2013-02-27T17:26:14.403 回答
0

你只需要检查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)
于 2018-02-15T12:16:46.543 回答
0

你可以这样做:

@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)
于 2020-11-24T19:14:56.067 回答
0

在我对另一个问题的回答中,我已经说明了最新的 Flask 建议。使用 Talisman 代替 SSLify。

对于 Flask 使用TalismanFlaskHerokuSSLify 文档更倾向于使用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。为此,请参阅 文档

于 2021-05-19T22:42:32.797 回答