Nasza aplikacja Django ma następujące wymagania dotyczące zarządzania sesjami.
- Sesje wygasają, gdy użytkownik zamyka przeglądarkę.
- Sesje wygasają po okresie bezczynności.
- Wykryj, kiedy sesja wygasa z powodu braku aktywności i wyświetl odpowiednią wiadomość użytkownikowi.
- Ostrzegaj użytkowników o zbliżającym się wygaśnięciu sesji na kilka minut przed końcem okresu bezczynności. Wraz z ostrzeżeniem należy udostępnić użytkownikom opcję przedłużenia sesji.
- Jeśli użytkownik pracuje nad długą działalnością biznesową w aplikacji, która nie obejmuje wysyłania żądań do serwera, sesja nie może przekraczać limitu czasu.
Po przeczytaniu dokumentacji, kodu Django i kilku związanych z tym postów na blogu, wymyśliłem następujące podejście do implementacji.
Wymaganie 1
To wymaganie można łatwo zaimplementować, ustawiając SESSION_EXPIRE_AT_BROWSER_CLOSE na True.
Wymaganie 2
Widziałem kilka zaleceń dotyczących używania SESSION_COOKIE_AGE do ustawiania okresu wygaśnięcia sesji. Ale ta metoda ma następujące problemy.
Sesja zawsze wygasa z końcem SESSION_COOKIE_AGE, nawet jeśli użytkownik aktywnie korzysta z aplikacji. (Można temu zapobiec, ustawiając wygaśnięcie sesji na SESSION_COOKIE_AGE dla każdego żądania przy użyciu niestandardowego oprogramowania pośredniczącego lub zapisując sesję dla każdego żądania, ustawiając SESSION_SAVE_EVERY_REQUEST na true. Jednak następny problem jest nieunikniony ze względu na użycie SESSION_COOKIE_AGE.)
Ze względu na sposób działania plików cookie, SESSION_EXPIRE_AT_BROWSER_CLOSE i SESSION_COOKIE_AGE wykluczają się wzajemnie, tj. Plik cookie wygasa po zamknięciu przeglądarki lub w określonym czasie wygaśnięcia. Jeśli używana jest SESSION_COOKIE_AGE, a użytkownik zamyka przeglądarkę przed wygaśnięciem pliku cookie, plik cookie zostaje zachowany, a ponowne otwarcie przeglądarki umożliwi użytkownikowi (lub komukolwiek innemu) dostęp do systemu bez ponownego uwierzytelniania.
Django opiera się tylko na obecnym pliku cookie, aby określić, czy sesja jest aktywna. Nie sprawdza daty wygaśnięcia sesji przechowywanej w sesji.
Aby zaimplementować to wymaganie i obejść powyższe problemy, można zastosować następującą metodę.
- Nie ustawiaj SESSION_COOKIE_AGE.
- Ustaw datę wygaśnięcia sesji na „bieżący czas + okres bezczynności” dla każdego żądania.
- Zastąp process_request w SessionMiddleware i sprawdź wygaśnięcie sesji. Odrzuć sesję, jeśli wygasła.
Wymaganie 3
Gdy wykryjemy, że sesja wygasła (w niestandardowym SessionMiddleware powyżej), ustaw atrybut w żądaniu, aby wskazać wygaśnięcie sesji. Atrybut ten może służyć do wyświetlania użytkownikowi odpowiedniego komunikatu.
Wymaganie 4
Użyj JavaScript, aby wykryć brak aktywności użytkownika, przekazać ostrzeżenie, a także opcję przedłużenia sesji. Jeśli użytkownik chce przedłużyć sesję, wyślij do serwera impuls podtrzymujący, aby przedłużyć sesję.
Wymaganie 5
Użyj JavaScript do wykrywania aktywności użytkownika (podczas długich operacji biznesowych) i wysyłaj impulsy podtrzymujące do serwera, aby zapobiec wygaśnięciu sesji.
Powyższe podejście do implementacji wydaje się bardzo skomplikowane i zastanawiałem się, czy nie ma prostszej metody (szczególnie dla Wymagania 2).
Wszelkie spostrzeżenia będą bardzo mile widziane.
Odpowiedzi:
Oto pomysł ... Wygaś sesję po zamknięciu przeglądarki z
SESSION_EXPIRE_AT_BROWSER_CLOSE
ustawieniem. Następnie ustaw znacznik czasu w sesji dla każdego takiego żądania.request.session['last_activity'] = datetime.now()
i dodaj oprogramowanie pośredniczące, aby wykryć, czy sesja wygasła. coś takiego powinno obsłużyć cały proces ...
from datetime import datetime from django.http import HttpResponseRedirect class SessionExpiredMiddleware: def process_request(request): last_activity = request.session['last_activity'] now = datetime.now() if (now - last_activity).minutes > 10: # Do logout / expire session # and then... return HttpResponseRedirect("LOGIN_PAGE_URL") if not request.is_ajax(): # don't set this for ajax requests or else your # expired session checks will keep the session from # expiring :) request.session['last_activity'] = now
Następnie wystarczy utworzyć adresy URL i widoki, aby zwrócić odpowiednie dane do wywołań Ajax dotyczących wygaśnięcia sesji.
gdy użytkownik zdecyduje się „odnowić” sesję, że tak powiem, wszystko, co musisz zrobić, to ponownie ustawić
requeset.session['last_activity']
aktualny czasOczywiście ten kod to dopiero początek ... ale powinien poprowadzić Cię na właściwą ścieżkę
źródło
if not request.is_ajax()
jest to całkowicie bezpieczne. Czy ktoś, kto przechwyci sesję przed wygaśnięciem, może sfałszować / wysłać połączenie AJAX i podtrzymać sesję?Jestem całkiem nowy w używaniu Django.
Chciałem, aby sesja wygasła, jeśli zalogowany użytkownik zamknie przeglądarkę lub jest w stanie bezczynności (limit czasu nieaktywności) przez pewien czas. Kiedy wyszukałem to w Google, aby dowiedzieć się, najpierw pojawiło się to pytanie SOF. Dzięki ładnej odpowiedzi wyszukałem zasoby, aby zrozumieć, jak działa oprogramowanie pośredniczące podczas cyklu żądanie / odpowiedź w Django. To było bardzo pomocne.
Miałem właśnie zastosować niestandardowe oprogramowanie pośredniczące w moim kodzie, postępując zgodnie z najlepszą odpowiedzią tutaj. Ale nadal byłem trochę podejrzliwy, ponieważ najlepsza odpowiedź tutaj została zredagowana w 2011 roku. Poświęciłem więcej czasu na przeszukiwanie ostatnich wyników wyszukiwania i wymyśliłem prosty sposób.
SESSION_EXPIRE_AT_BROWSER_CLOSE = True SESSION_COOKIE_AGE = 10 # set just 10 seconds to test SESSION_SAVE_EVERY_REQUEST = True
Nie sprawdzałem innych przeglądarek poza chrome. 1. Sesja wygasła, kiedy zamknąłem przeglądarkę, nawet jeśli ustawiono SESSION_COOKIE_AGE. 2. Tylko gdy byłem bezczynny przez ponad 10 sekund, sesja wygasła. Dzięki SESSION_SAVE_EVERY_REQUEST, za każdym razem, gdy pojawi się nowe żądanie, zapisuje sesję i aktualizuje limit czasu do wygaśnięcia
Aby zmienić to domyślne zachowanie, ustaw SESSION_SAVE_EVERY_REQUEST na True. Gdy ustawione na True, Django zapisze sesję w bazie danych przy każdym żądaniu.
Należy pamiętać, że plik cookie sesji jest wysyłany tylko wtedy, gdy sesja została utworzona lub zmodyfikowana. Jeśli SESSION_SAVE_EVERY_REQUEST ma wartość True, plik cookie sesji będzie wysyłany przy każdym żądaniu.
Podobnie, część wygasłego pliku cookie sesji jest aktualizowana za każdym razem, gdy wysyłany jest plik cookie sesji.
Podręcznik django 1.10
Po prostu zostawiam odpowiedź, aby niektórzy ludzie, którzy są nowicjuszami w Django, tacy jak ja, nie spędzali zbyt wiele czasu na szukaniu rozwiązania, tak jak ja.
źródło
django-session-security robi właśnie to ...
... z dodatkowym wymaganiem: jeśli serwer nie odpowiada lub osoba atakująca rozłączyła połączenie internetowe: i tak powinno wygasnąć.
Disclamer: utrzymuję tę aplikację. Ale oglądam ten wątek od bardzo, bardzo długiego czasu :)
źródło
Prostym sposobem spełnienia drugiego wymagania byłoby ustawienie wartości SESSION_COOKIE_AGE w settings.py na odpowiednią liczbę sekund. Na przykład:
SESSION_COOKIE_AGE = 600 #10 minutes.
Jednak tylko w ten sposób sesja wygaśnie po 10 minutach, niezależnie od tego, czy użytkownik wykaże jakąś aktywność. Aby poradzić sobie z tym problemem, czas wygaśnięcia może być automatycznie przedłużany (o kolejne dodatkowe 10 minut) za każdym razem, gdy użytkownik wykona dowolny rodzaj żądania z następującym zdaniem:
źródło
SESSION_COOKIE_AGE
wystarczy i że każde żądanie (wysłanie sesyjnego pliku cookie) automatycznie odświeży datę wygaśnięcia sesji.możesz również użyć funkcji wbudowanych w stackoverflow
SESSION_SAVE_EVERY_REQUEST = True
źródło
W pierwszym żądaniu możesz ustawić wygaśnięcie sesji jako
self.request.session['access_key'] = access_key self.request.session['access_token'] = access_token self.request.session.set_expiry(set_age) #in seconds
Korzystając z klucza dostępu i tokena,
try: key = self.request.session['access_key'] except KeyError: age = self.request.session.get_expiry_age() if age > set_age: #redirect to login page
źródło