python flask从http重定向到https

Dav*_*uan 18 python ssl flask

我有一个使用python3.4和烧瓶的网站构建...我已经生成了自己的自签名证书,我目前正在通过localhost测试我的网站.

我正在使用python ssl模块以及这个烧瓶扩展:https://github.com/kennethreitz/flask-sslify

context = ('my-cert.pem', 'my-key.pem')
app = Flask(__name__)
sslify = SSLify(app)

...

if __name__ == '__main__':
    app.debug = False
    app.run(
    host="127.0.0.1",
    port=int("5000"),
    ssl_context=context
)
Run Code Online (Sandbox Code Playgroud)

然而,这似乎不起作用.我查看了sslify源代码,这行似乎没有用

def init_app(self, app):
    """Configures the configured Flask app to enforce SSL."""
    app.before_request(self.redirect_to_ssl)
    app.after_request(self.set_hsts_header)
Run Code Online (Sandbox Code Playgroud)

特别是函数调用redirect_to_ssl(我在redirect_to_ssl函数下添加了我自己的print语句,我的语句从未打印过)

def redirect_to_ssl(self):
    print("THIS IS WORKING")
    """Redirect incoming requests to HTTPS."""
    Should we redirect?
    criteria = [
        request.is_secure,
        current_app.debug,
        request.headers.get('X-Forwarded-Proto', 'http') == 'https'
    ]

    if not any(criteria) and not self.skip:
        if request.url.startswith('http://'):
            url = request.url.replace('http://', 'https://', 1)
            code = 302
            if self.permanent:
                code = 301
            r = redirect(url, code=code)
            return r
Run Code Online (Sandbox Code Playgroud)

我对python很新.有任何想法吗?

Kel*_*ila 31

对我来说,似乎你让它变得比它需要的更复杂.以下是我在views.py脚本中使用的代码,用于强制用户进行HTTPS连接:

@app.before_request
def before_request():
    if request.url.startswith('http://'):
        url = request.url.replace('http://', 'https://', 1)
        code = 301
        return redirect(url, code=code)
Run Code Online (Sandbox Code Playgroud)

  • 应该是request.is_secure (3认同)
  • 我不确定它会如何重定向不止一次,除非你有其他的东西从https重定向到某个地方的http,创建一个循环.它应该只重定向一次. (2认同)
  • 我认为更改很简单:`if not request.is_secure():` 如下@tuned 所述。 (2认同)

Eya*_*vin 14

瓶安全指南建议使用瓶,护符

$ pip install flask-talisman
Run Code Online (Sandbox Code Playgroud)

用法示例:

$ pip install flask-talisman
Run Code Online (Sandbox Code Playgroud)

HTTPS默认强制(来自自述文件):

force_https, 默认True, 强制所有非调试连接到https.


就我个人而言,我遇到了一些与我禁用的 CSP(内容安全策略)相关的错误:

from flask import Flask
from flask_talisman import Talisman

app = Flask(__name__)
Talisman(app)
Run Code Online (Sandbox Code Playgroud)

但使用它需要您自担风险:)


Rod*_*rez 13

根据文档,pip install Flask-SSLify您只需要插入以下代码:

from flask import Flask
from flask_sslify import SSLify

app = Flask(__name__)
sslify = SSLify(app)
Run Code Online (Sandbox Code Playgroud)

我做到了,效果很好.我在讨论中遗漏了什么吗?


anu*_*bar 10

由于从答案凯利·凯勒,Heikkila和评论通过jaysqrd我结束了我的瓶的应用程序这样做:

from flask import request, redirect
...

@app.before_request
def before_request():
    if app.env == "development":
        return
    if request.is_secure:
        return

    url = request.url.replace("http://", "https://", 1)
    code = 301
    return redirect(url, code=code)
Run Code Online (Sandbox Code Playgroud)

我尝试了Rodolfo Alvarezflask_sslify建议的解决方案,但遇到了这个问题,而是采用了上述解决方案。

如果应用程序在开发模式下运行或请求已经在 https 上,则无需重定向。


edW*_*edW 7

如果您在 aws 上并在负载均衡器后面,这是一个烧瓶解决方案。把它放在你的 views.py 中

@app.before_request
def before_request():
    scheme = request.headers.get('X-Forwarded-Proto')
    if scheme and scheme == 'http' and request.url.startswith('http://'):
        url = request.url.replace('http://', 'https://', 1)
        code = 301
        return redirect(url, code=code)
Run Code Online (Sandbox Code Playgroud)


tun*_*ned 5

标准解决方案是使用enforce_ssl装饰器包装请求,该装饰器在检查了应用程序配置中的某些标志(可以根据调试需求设置的标志)后,使用修饰符request.url

正如它写在这里

您可以before_request按照@ kelly-keller-heikkila的建议修改代码以使其工作


小智 5

我使用一个在端口 80 上运行的简单的额外应用程序,并将人们重定向到 https:

from flask import Flask,redirect

app = Flask(__name__)

@app.route('/')
def hello():
    return redirect("https://example.com", code=302)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)
Run Code Online (Sandbox Code Playgroud)