2011-12-08 13 views
47

Mam aplikację python/django na Heroku (stos cedrowy) i chciałbym, aby była dostępna tylko przez https. Włączyłem opcję "ssl piggyback" i mogę połączyć się z nią przez https.Jak zrobić python na Heroku tylko https?

Ale jaki jest najlepszy sposób na wyłączenie dostępu http lub przekierowanie do https?

Odpowiedz

63

Łącząc odpowiedź z @CraigKerstiens i @allanlei na coś, co przetestowałem i zweryfikowałem, że działa. Heroku ustawia HTTP_X_FORWARDED_PROTO do https gdy wniosek jest SSL, a my możemy to wykorzystać do sprawdzenia:

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) 
+27

Odpowiedź jest teraz [aplikacja na github] (https://github.com/rdegges/django-sslify) –

+1

Awans na wprowadzenie github ... Dzięki! Właśnie tego szukałem dzisiaj. –

+3

Na marginesie, to nie działa, jeśli DEBUG ma wartość True. Spędziłem godzinę, wymyślając to jedno, więc mam nadzieję, że to kogoś oszczędza. – Femi

6

Jakie ramy stosujesz w swojej aplikacji? Jeśli korzystasz z Django można użyć niektórych middleware prosty podobny do:

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) 
+0

Tak, używam django. Dziękuję za odpowiedź: spróbuję, chyba że pojawi się coś prostszego (np. Ukryta opcja Heroku). – Kristian

+0

Musiałem wprowadzić drobną poprawkę, ale moderatorzy odrzucili moją edycję. Stworzyłem własną odpowiedź, która rozwiązuje problem z niekończącymi się przekierowaniami w bieżącej odpowiedzi.Dzięki, nigdy nie pomyślałbyś o rozwiązaniu typu middleware bez twojego wkładu. – Kristian

+1

To rozwiązanie tworzy niekończącą się pętlę przekierowania. Zobacz moją odpowiedź powyżej .. – Kristian

13

Nie wiem czy @ CraigKerstiens na odpowiedź uwzględnia fakt, że request.is_secure() zawsze zwraca False jeśli za reverse proxy Heroku a nie „stałe”. Jeśli dobrze pamiętam, spowoduje to pętlę przekierowania HTTP.

Jeśli używasz Django z gunicorn, innym sposobem na to jest dodanie następujących do gunicorn na config

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

Uruchom z jednymi jak to w swoim Procfile

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

Ustawiając gunicorn-tych secure-scheme-header, request.is_secure() prawidłowo zwróci True na prośby https. Zobacz Gunicorn Config.

Teraz oprogramowanie pośredniczące middleware @ CraigKerstiens będzie działać poprawnie, w tym wszelkie połączenia z numerem request.is_secure() w aplikacji.

Uwaga: Django ma również to samo ustawienie konfiguracyjne, wywołanie SECURE_PROXY_SSL_HEADER, ale w wersji dla deweloperów.

+2

Ustawienie dudego SECURE_PROXY_SSL_HEADER jest już dostępne w głównej linii (na pewno w 1.6, może wcześniej). – Symmetric

4

Jeśli używasz kolbie to działa całkiem dobrze:

1) Czy „pip zainstalować flask- sslify”

(github jest tutaj: https://github.com/kennethreitz/flask-sslify)

2) zawierać następujące linie:

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

Jeśli to zrobimy ... czy nadal musimy robić rzeczy Heroku? Przepraszam, trochę nowego w tych rzeczach. – John

+0

Mimo to zobacz ponownie problem "flip-flop" na stronie https://github.com/kennethreitz/flask-sslify/issues/3 – wodow

33

Django 1,8 będzie miała podstawową obsługę niż HTTPS przekierowania (zintegrowany z django-secure)

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

Aby w SECURE_SSL_REDIRECT być obsługiwane trzeba użyć SecurityMiddleware:

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

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

+0

Czy to oznacza, że ​​sslify pakietów pip są przestarzałe od Django 1.8? – dfrankow

+0

@dfrankow django-sslify brzmi podobnie do django-secure, ale musisz to potwierdzić z autorem pakietu – shangxiao

+0

@dfrankow Nie, nadal potrzebujesz sslify z Django 1.8, jeśli chcesz automatycznie przekierowywać użytkowników z http na https . –