web-dev-qa-db-fra.com

Comment faire python sur Heroku https uniquement?

J'ai une application python/Django sur Heroku (pile Cedar) et je voudrais la rendre accessible via https uniquement. J'ai activé l'option "ssl piggyback" et je peux me connecter via https.

Mais quelle est la meilleure façon de désactiver l'accès http ou de rediriger vers https?

55
Kristian

Combiner la réponse de @CraigKerstiens et @allanlei en quelque chose que j'ai testé et vérifié pour fonctionner. Heroku définit HTTP_X_FORWARDED_PROTO sur https lorsque la demande est SSL, et nous pouvons l'utiliser pour vérifier:

from Django.conf import settings
from Django.http import HttpResponseRedirect


class SSLMiddleware(object):

    def process_request(self, request):
        if not any([settings.DEBUG, request.is_secure(), request.META.get("HTTP_X_FORWARDED_PROTO", "") == 'https']):
            url = request.build_absolute_uri(request.get_full_path())
            secure_url = url.replace("http://", "https://")
            return HttpResponseRedirect(secure_url)
64
Kristian

Django 1.8 aura un support de base pour la redirection non HTTPS (intégré à partir de Django-secure ):

SECURE_SSL_REDIRECT = True # [1]
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

Pour SECURE_SSL_REDIRECT pour être manipulé, vous devez utiliser le SecurityMiddleware:

MIDDLEWARE = [
    ...
    'Django.middleware.security.SecurityMiddleware',
]

[1] https://docs.djangoproject.com/en/1.8/ref/settings/#secure-ssl-redirect

48
shangxiao

Je ne sais pas si la réponse de @ CraigKerstiens tient compte du fait que request.is_secure() renvoie toujours False si derrière le proxy inverse de Heroku et non "fixe". Si je me souviens bien, cela provoquera une boucle de redirection HTTP.

Si vous exécutez Django avec gunicorn, une autre façon de le faire est d'ajouter ce qui suit à la configuration de gunicorn

secure_scheme_headers = {
    'X-FORWARDED-PROTO': 'https'
}

Exécuter avec certains comme celui-ci dans votre Procfile

web: python manage.py run_gunicorn -b 0.0.0.0:$PORT -c config/gunicorn.conf

En définissant le secure-scheme-header De gunicorn, request.is_secure() renverra correctement True sur les requêtes https. Voir Gunicorn Config .

Le middleware de @ CraigKerstiens fonctionnera désormais correctement, y compris tous les appels à request.is_secure() dans votre application.

Remarque: Django a également le même appel de paramètre de configuration SECURE_PROXY_SSL_HEADER, Mais dans la version de développement.

13
Allan Lei

Quel cadre utilisez-vous pour votre application? Si vous utilisez Django vous pouvez simplement utiliser un middleware similaire à:

import re

from Django.conf import settings
from Django.core import urlresolvers
from Django.http import HttpResponse, HttpResponseRedirect


class SSLMiddleware(object):

    def process_request(self, request):
        if not any([settings.DEBUG, request.is_secure()]):
            url = request.build_absolute_uri(request.get_full_path())
            secure_url = url.replace("http://", "https://")
            return HttpResponseRedirect(secure_url)
6
CraigKerstiens

Si vous utilisez Flask, cela fonctionne très bien:

1) Faites "pip install flask-sslify"

(github est ici: https://github.com/kennethreitz/flask-sslify )

2) Incluez les lignes suivantes:

from flask_sslify import SSLify
if 'DYNO' in os.environ: # only trigger SSLify if the app is running on Heroku
    sslify = SSLify(app)
4
Ryan