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 connexion https, le url_for
me donne toujours http.
Je voudrais demander explicitement url_for
pour ajouter https au début d'une URL.
Pouvez-vous me montrer comment le changer? J'ai regardé Flask docs, sans chance.
Avec Flask 0.10, il y aura une bien meilleure solution disponible que l'emballage url_for
. Si vous regardez https://github.com/mitsuhiko/flask/commit/b5069d07a24a3c3a54fb056aa6f4076a0e7088c7 , un _scheme
le paramètre a été ajouté. Cela signifie que vous pouvez effectuer les opérations suivantes:
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 aller de /secure_thingy
à https://example.com/secure_thingy
.
Cependant, pensez plutôt à rendre votre site Web uniquement en HTTPS. 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 https-URL n'est pas modifiée si la page reliant à la page sécurisée n'est pas cryptée. Ceci est similaire à contenu mixte .
Si vous souhaitez 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 "bonne" réponse soit d'utiliser le middleware WSGI, comme dans cet extrait: http://flask.pocoo.org/snippets/35/
( Ce Flask semble confirmer que c'est la méthode préférée.)
Fondamentalement, si votre environnement WSGI a environ['wsgi.url_scheme'] = 'https'
, puis url_for
générera https:
URL.
Je devenais http://
URL 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 standard. Ma solution (spécifique à Elastic Beanstalk) était la suivante (simplifiée à partir de l'extrait de code 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 à Elastic Beanstalk est HTTP_X_FORWARDED_PROTO
. D'autres environnements auraient d'autres moyens de déterminer si l'URL externe incluait https. Si vous voulez simplement toujours utiliser HTTPS, vous pouvez définir inconditionnellement environ['wsgi.url_scheme'] = 'https'
.
PREFERRED_URL_SCHEME
n'est pas la solution. C'est ignoré chaque fois qu'une demande est en cours .
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
variable de configuration et définissez-la sur https avec:
app.config.update(dict(
PREFERRED_URL_SCHEME = 'https'
))
puisque vous n'avez pas à l'ajouter à chaque url_for
appel.
Si vous accédez à votre site Web via un proxy inverse comme Nginx, alors Flask détecte correctement le schéma étant HTTP
.
Browser -----HTTPS----> Reverse proxy -----HTTP----> Flask
La solution la plus simple consiste à configurer votre proxy inverse pour définir le X-Forwarded-Proto
entête. Flask détectera automatiquement cet en-tête et gérera le schéma en conséquence. Il y a ne explication plus détaillée dans la documentation Flask sous la section Proxy Setups =. Par exemple, si vous utilisez Nginx, vous devrez ajouter la ligne suivante dans votre bloc location
.
proxy_set_header X-Forwarded-Proto $scheme;
Comme mentionné, si vous ne pouvez pas modifier la configuration de votre proxy, vous pouvez soit utiliser le ProxyFix werkzeug, soit créer votre propre correctif comme décrit dans la documentation: http://flask.pocoo.org/docs/ 0.12/deploying/wsgi-standalone/# proxy-setups
Définir _scheme
Sur chaque appel à url_for()
est extrêmement fastidieux et PREFERRED_URL_SCHEME
Ne semble pas fonctionner. Cependant, le nettoyage avec le schéma supposé de la requête au niveau WSGI semble convaincre avec succès Flask pour 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)