Python flask перенаправить на https с http

У меня есть сборка сайта с использованием python3.4 и фл... Я создал свой собственный самозаверяющий сертификат, и сейчас я тестирую свой сайт через localhost.

Я использую модуль ssl python вместе с этим расширением фляжки: 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
)

Однако это, похоже, не работает. Я взглянул в исходный код 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)

В частности, вызов функции redirect_to_ssl (я добавил свой собственный оператор печати под функцию redirect_to_ssl, и мое выражение никогда не печаталось)

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

Я новичок в python. Любые идеи?

Ответ 1

Для меня, похоже, вы делаете это более сложным, чем нужно. Вот код, который я использую в своих view.py script, чтобы заставить пользователей подключаться к 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)

Ответ 2

Согласно документации, после pip install Flask-SSLify вам нужно всего лишь вставить следующий код:

from flask import Flask
from flask_sslify import SSLify

app = Flask(__name__)
sslify = SSLify(app)

Я сделал это, и это работает очень хорошо. Я что-то упускаю в обсуждении?

Ответ 3

Стандартное решение состоит в том, чтобы обернуть запрос декоратором enforce_ssl который после проверки некоторых флагов в конфигурации приложения (флаги, которые вы можете установить в зависимости от ваших потребностей в отладке) изменяет URL-адрес запроса с помощью request.url.

Как написано здесь.

Вы можете изменить код, чтобы он работал с before_request как предложено @kelly-keller-heikkila

Ответ 4

Благодаря ответу Келли Келлер-Хейккила и комментарию jaysqrd я сделал это в своем приложении Flask:

from flask import request, redirect
...

@app.before_request
def before_request():
    if not request.is_secure and app.env != "development":
        url = request.url.replace("http://", "https://", 1)
        code = 301
        return redirect(url, code=code)

Я попробовал решение flask_sslify предложенное Родольфо Альваресом, но столкнулся с этой проблемой и вместо этого использовал вышеуказанное решение.

Проверка app.env позволяет запустить модульные тесты и локальную разработку без https.

Ответ 5

Руководство по безопасности Flask рекомендует использовать Flask-Talisman.

$ pip install flask-talisman

Пример использования:

from flask import Flask
from flask_talisman import Talisman

app = Flask(__name__)
Talisman(app)

По умолчанию он вызывает HTTPS (из README):

force_https, default True, forces all non-debug connects to https.


Лично я получил несколько ошибок, связанных с CSP (Content Security Policy), которые я отключил с помощью:

Talisman(app, content_security_policy=None)

Но используйте это на свой страх и риск :)

Ответ 6

Я использую простое дополнительное приложение, которое работает на порту 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)