2017-10-16 76 views
14

Nasza strona DjangoCMS jest dostępna przez http i https.DjangoCMS: wyłącz logowanie przez http, wymusza https

Anonimowe użycie przez http jest w porządku. Ale chcę wyłączyć logowanie przez http.

Czy istnieje sposób na wymuszenie korzystania z https, gdy tylko użytkownik chce się zalogować?

Nawet strona logowania (z polami nazwy użytkownika i hasła) nie powinna być dostępna przez http.

Tło: Nie chcę, aby hasło przechodziło przez przewód niezaszyfrowany.

Aktualizacja: Witryna jest hostowana na serwerze WWW Apache.

+2

Dlaczego nie przekierować całego ruchu do https? –

+2

Cóż, jest to jedna strona logowania jako HTTPS, ale co jest z ciasteczkami po uwierzytelnieniu użytkownika? IMHO powinno się wyświetlać tylko HTTPS, a nie tylko wtedy, gdy użytkownik chce się zalogować. – Thomas

+0

@ user1 Do tej pory nie myślałem o tym szczególe. – guettli

Odpowiedz

12

Jak już wspomniałem w komentarzach, zdecydowanie sugeruję, aby NOT wyświetlać tylko stronę logowania przez https.

W ten sposób ukrywa się fakt, że np. Informacje o sesji i dane uwierzytelniające są nadal przesyłane na inne żądania niezaszyfrowane przez http.Twoja strona nie będzie w ogóle bezpieczna.

Jesteś po prostu pseudo-zabezpieczeniem rzeczy, więc jest to fantazyjne dla oka. To tak jak przy użyciu hasła 12345.

Więc proszę podać swoją stronę internetową ponad https użytkownikowi. Mały przewodnik dla nginx lub apache2, w jaki sposób przekierować ruch z http do https można znaleźć tutaj:

+3

Twoja odpowiedź nie pasuje do mojego pytania :-) Ale: Tak, masz rację. Nadszedł czas, aby serwer wszystko przez https. Chyba będę używał https://letsencrypt.org/ – guettli

3

prośba Django ma is_secure()

Można to sprawdzić w widoku i przekierować jeśli nie jest bezpieczny:

if not request.is_secure(): 
    return redirect("https://www.yourdomain.com/login") 
+0

Powyższy fragment kodu wygląda dobrze. Ale gdzie powinienem umieścić te dwie linie? – guettli

+0

W widoku, który chcesz wymusić https. Na przykład widok logowania. Jeśli jest to widok ogólny, możesz użyć get_context_data lub opublikować swój widok logowania i mogę zasugerować ci gdzie. – Zartch

3

@ użytkownika1 ma prawo logiki i powinno służyć swoją witrynę poprzez https, aby był bezpieczny.
Ale aby odpowiedzieć dokładną pytanie:

Jak pokazano tutaj: How to know using Django if server is secure (uses https) i jak @Zartch wspomina w swojej odpowiedzi, należy użyć metody is_secure() HTTPRequest aby sprawdzić, czy żądanie pochodzi przez https.

  • Aby korzystać is_secure() trzeba sprawdzić przychodzące żądania do swoich poglądów:

    def my_login_view(request): 
        if request.is_secure(): 
         Do loggin 
        else: 
         Don't login 
    
  • Teraz można chronić swoje inne widoki z login_required dekoratora:

    @login_required(login_url='/your/login/url') 
    def protected_view(request): 
        ... 
    

osobista sugestia: używam Django Rest Framework obszernie i chciałbym to sugerować, w danym przypadku, ponieważ ma klasę isAuthenticatedOrReadOnly uprawnień które lubisz:

class MyLoginView(ObtainAuthToken): 
    """ 
    Login view for token-based authentication 
    """ 
    def post(self, request, *args, **kwargs): 
     if request.is_secure(): 
      super().post(request, *args, **kwargs) 
     else: 
      Probably some redirect goes here... 

Następnie w każdym innym widoku lub widoku klasy opartej :

class MyOtherView(generics.GenericAPIView): 
    authentication_classes = (TokenAuthentication,) 
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,) 
    ... 

powyższe zapewnia, że ​​użytkownicy mogą logować się tylko przy użyciu protokołu HTTPS, a jeśli nie są one rejestrowane w ujrzą tylko widok tylko do odczytu.

Spróbuj, jeśli chcesz.

2

Nie przyjmuję jeszcze odpowiedzi, więc pomyślałem, że odpowiedzi mogą nie odpowiadać wystarczająco dobrze.

Anonimowe użycie przez http jest w porządku. Ale chcę wyłączyć logowanie przez http.

Jak rozumiem, masz następujący przypadek użycia:

Niektóre osoba odwiedza Twoją stronę internetową jako anonimowego użytkownika, używany jest protokół http. Ta osoba otwiera formularz logowania i loguje się, formularz jest wysyłany przez https. Zalogowany użytkownik kontynuuje przeglądanie witryny za pośrednictwem protokołu https.

Jeśli formularz logowania zostanie przekierowany do bezpiecznej wersji, użytkownik będzie kontynuował przeglądanie witryny w trybie https (o ile wszystkie inne łącza nie są agnostyczne w stosunku do używanego protokołu).

<form action="https://your.domain/path/to/login/" method="post">

Jeśli aplikacja używasz do uwierzytelniania użytkowników zdrowo jest napisane, można skonfigurować settings.LOGIN_URL, jeszcze będzie potrzebne, aby to zrobić w formie szablonów.

Zalecam zezwolenie na wysyłanie plików cookie sesji za pośrednictwem protokołu https przy użyciu adresu settings.SESSION_COOKIE_SECURE. Przy tym ustawieniu użytkownik nadal będzie mógł wysyłać żądania http, ale plik cookie sesji nie zostanie wysłany (a użytkownik będzie traktowany jako anonimowy użytkownik).

Proszę się upewnić, że w widoku logowania akceptowane są tylko bezpieczne żądania pocztowe (w przeciwnym razie użytkownik może wysłać hasło za pomocą protokołu innego niż https). Można to osiągnąć w kodzie Django (jak sugeruje John Moutafis ze swoim MyLoginView) lub na poziomie serwera produkcyjnego, odrzucając żądania HTTPS dla adresu URL logowania.

-

Czy możesz zapewnić dostęp do repozytorium z kodem?

+0

"SESSION_COOKIE_SECURE" tylko sygnalizuje ciasteczko jako 'secure'. Nie wymusza to w ogóle dostarczania przez https. Jeśli ustawisz flagę i wyświetlisz swoją witrynę za pośrednictwem http, zamiast tego otrzymasz błędy "CSRF" z powodu tego ustawienia. – Thomas

+0

Witam user1! Być może będę musiał zmienić zdanie. Próbuję powiedzieć, że plik cookie jest wysyłany tylko wtedy, gdy połączenie jest bezpieczne. Nadal możesz wysyłać żądanie http, ale plik cookie nie zostanie wysłany w takim przypadku (a zatem nie ma sesji). –

4

Jak już zaakceptowałeś w komentarzach, przeniesienie całego ruchu do HTTPS jest obecnie najlepszym rozwiązaniem. Jeśli uwierzytelniasz tylko przez SSL, musisz wziąć pod uwagę szyfrowanie/bezpieczeństwo we wszystkim, co piszesz w ruchu do przodu, a nie tylko jako domyślne.

W konfiguracji serwera zmuś cały ruch do portu 443.Zakładając, że używasz Apache, zrobiłbyś to;

<VirtualHost *:80> 
    ServerName www.example.com 
    Redirect/https://www.example.com/ 
</VirtualHost> 

<VirtualHost *:443> 
    ServerName www.example.com 
    # ... SSL configuration goes here 
</VirtualHost> 

Następnie w ustawieniach Django włącz bezpieczne pliki cookie;

SESSION_COOKIE_SECURE = True 
CSRF_COOKIE_SECURE = True 

Na marginesie, Django ma ustawienia przekierowania ruchu HTTP na HTTPS, który jest SECURE_SSL_REDIRECT, ale jeśli robisz to na poziomie Apache/nginx nie trzeba się martwić. Więcej informacji na temat SSL/HTTPS można znaleźć tutaj; https://docs.djangoproject.com/en/1.11/topics/security/#ssl-https

0

Można użyć jednego lub kombinacji: