Flask url pour générer une URL http au lieu de https

J'utilise url_for pour générer une url de redirection lorsqu'un utilisateur s'est déconnecté.

return redirect(url_for('.index', _external=True))

Cependant, lorsque j'ai changé la page en une connexionhttps , le url_for me donne toujours http .

Je voudrais demander explicitement url_for pour ajouter https au début de l'url.

Pouvez-vous me montrer comment le changer? Je regarde Flask docs, sans chance.

Merci.

28
demandé sur Blaise 2013-02-11 14:56:21

5 réponses

Avec Flask 0.10, il y aura une bien meilleure solution disponible que wrapping url_for. Si vous regardez https://github.com/mitsuhiko/flask/commit/b5069d07a24a3c3a54fb056aa6f4076a0e7088c7 , un paramètre _scheme a été ajouté. Ce qui signifie que vous pouvez faire ce qui suit:

url_for('secure_thingy',
        _external=True,
        _scheme='https',
        viewarg1=1, ...)

_scheme définit le schéma D'URL, générant une URL comme https://.. au lieu de http://. Cependant, par défaut, Flask ne génère que des chemins (sans hôte ni schéma), vous devrez donc inclure le _external=True pour passer de /secure_thingy à https://example.com/secure_thingy.


Cependant, pensez à rendre votre site Web HTTPS uniquement à la place. Il semble que vous essayez d'appliquer partiellement HTTPS pour seulement quelques routes "sécurisées", mais vous ne pouvez pas vous assurer que votre URL https n'est pas modifiée si la page reliant à la page sécurisée n'est pas cryptée. Ceci est similaire à contenu mixte.

40
répondu Markus Unterwaditzer 2018-01-27 20:28:17

J'ai essayé la réponse acceptée avec un url_for arg mais j'ai trouvé plus facile d'utiliser le PREFERRED_URL_SCHEME config variable et définissez-la sur https avec:

app.config.update(dict(
  PREFERRED_URL_SCHEME = 'https'
))

, Puisque vous n'avez pas à l'ajouter à tous les url_for appeler.

19
répondu dajobe 2015-02-12 16:39:37

Si vous voulez affecter le schéma D'URL pour toutes les URL générées par le serveur (url_for et redirect), plutôt que d'avoir à définir _scheme à chaque appel, il semble que la réponse "correcte" soit d'utiliser le middleware WSGI, comme dans cet extrait: http://flask.pocoo.org/snippets/35/

(Ce bug Flask {[14] } semble confirmer que c'est le moyen préféré.)

Fondamentalement, si votre environnement WSGI a environ['wsgi.url_scheme'] = 'https', alors url_for générera des URL https:.

Je recevais des URLs http:// de url_for parce que mon serveur a été déployé derrière un équilibreur de charge Elastic Beanstalk, qui communique avec le serveur en HTTP régulier. Ma solution (spécifique à Elastic Beanstalk) était comme ceci (simplifié à partir de l'extrait lié ci-dessus):

class ReverseProxied(object):
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        scheme = environ.get('HTTP_X_FORWARDED_PROTO')
        if scheme:
            environ['wsgi.url_scheme'] = scheme
        return self.app(environ, start_response)

app = Flask(__name__)
app.wsgi_app = ReverseProxied(app.wsgi_app)

La partie spécifique au haricot élastique est HTTP_X_FORWARDED_PROTO. D'autres environnements auraient d'autres moyens de déterminer si l'URL externe incluait https. Si vous voulez juste toujours utiliser HTTPS, vous pouvez définir inconditionnellement environ['wsgi.url_scheme'] = 'https'.

PREFERRED_URL_SCHEME n'est pas la façon de le faire. Il est ignoré chaque fois qu'une requête est en cours .

18
répondu aldel 2016-06-15 17:53:12

Définir _scheme sur chaque appel url_for() est extrêmement fastidieux, et PREFERRED_URL_SCHEME ne semble pas fonctionner. Cependant, se débarrasser de ce que le schéma supposé de la requête est au niveau WSGI semble convaincre avec succès Flask de toujours construire des URL HTTPS:

def _force_https(app):
    def wrapper(environ, start_response):
        environ['wsgi.url_scheme'] = 'https'
        return app(environ, start_response)
    return wrapper

app = Flask(...)

app = _force_https(app)
6
répondu cvrebert 2015-01-31 02:34:43

Si vous accédez à votre site web via un proxy, Flask dectects correctement le schéma étant HTTP.

Browser -----HTTPS----> Proxy -----HTTP----> Flask

La solution la plus simple consiste à configurer votre proxy pour définir l'en-tête X-Forwarded-Proto. Flask détecte automatiquement cet en-tête et gère le schéma en conséquence. Il y a une explication plus détaillée dans la documentation Flask sous la section Configurations de Proxy . Par exemple, si vous utilisez Nginx, vous devrez ajouter la ligne suivante dans votre location bloc.

proxy_set_header   X-Forwarded-Proto    $scheme;

Comme autre mentionné, si vous ne pouvez pas changer la configuration de votre proxy, vous pouvez utiliser le ProxyFix de werkzeug ou construire votre propre correctif comme décrit dans la documentation: http://flask.pocoo.org/docs/0.12/deploying/wsgi-standalone/#proxy-setups

6
répondu Timothée Jeannin 2017-08-15 12:45:27