Obsługa limitów czasu sesji użytkownika w aplikacjach SaaS - omówienie kilku podejść


11

Wiem, że ma to duże szanse na oznaczenie jako duplikat, ale nie mogłem znaleźć dokładnie tego, czego szukam

Jest to powszechny problem i jestem pewien, że ma dobrze zdefiniowane najlepsze rozwiązanie

tło

  1. Jednostronicowa aplikacja SaaS ma wiele funkcji „przeciągnij i upuść”, użytkownik może z nią korzystać przez długi czas bez komunikacji z serwerem

  2. Sesja serwera przechowuje tylko obiekt użytkownika, używając nietrwałego pliku cookie sesji

  3. Sesja wygasa na serwerze po X godzinach

  4. Niektóre rzeczy są ładowane tylko podczas logowania

Problem

  1. Użytkownik działa w aplikacji, gdy skończysz, użytkownik się nie wylogowuje, po prostu utrzymuje przeglądarkę otwartą
  2. Użytkownik wraca po ponad X godzinach (sesja jest unieważniona na serwerze)
  3. Użytkownik wchodzi w interakcję z aplikacją bez potrzeby połączenia z serwerem (przeciąganie i upuszczanie elementów, edycja tekstu ...)
  4. Tylko przy następnej interakcji z serwerem (załóżmy, że nie ma automatycznego zapisywania) użytkownik zostaje przeniesiony na stronę logowania i traci część swojej pracy

Możliwe rozwiązania

Oto kilka rozwiązań, które mam na myśli, chciałbym usłyszeć, czy są jakieś inne, a jeśli coś jest zasadniczo nie tak z którymkolwiek z nich.

1. Nigdy nie wylogowuj użytkownika

  • W jaki sposób? albo utrzymuj długą sesję, zachowaj trwałe ciasteczko, albo javaScript „keep alive” ping
  • Plusy : użytkownik nie musi się o nic martwić, naprawia dla nich problem
  • Wady : niezgodny z PCI, niezabezpieczony i wymaga zmian programistycznych, np. Rzeczy załadowane do sesji tylko przy logowaniu użytkownika muszą przejść do podmodelu pub (słuchanie zmian zdarzeń) lub mieć limit czasu pamięci podręcznej.

2. Lokalne przechowywanie

  • W jaki sposób? użyj nowej pamięci lokalnej, aby tymczasowo zapisać stan po wylogowaniu, przekieruj na stronę logowania, zachowaj po zalogowaniu
  • Plusy : podstawa do obsługi „pracy offline”, a nie tylko obsługi limitu czasu sesji
  • Minusy : trudniejsze do wdrożenia, należy wykonać scalanie stanu drzewa danych, nie wszystkie przeglądarki obsługują

3. Automatyczne zapisywanie

Każda czynność użytkownika, która zmienia model, powinna być natychmiastowa (lub za pośrednictwem jakiejś kolejki po stronie klienta), np. Jeśli zaznaczą pole wyboru, zmienią pole tekstowe lub przeciągną i upuszczą coś, gdy zostaną wykonane, zachowają zmiany.

  • W jaki sposób? Użyj frameworka MV ** (Backbone.js / Knockout.js / Ember.js / Angular.js itp.), Aby powiązać model i zachować zmiany.
  • Zalety : Wydaje się, że jest to czyste rozwiązanie, sesja jest aktywna tak długo, jak długo użytkownik jest aktywny, żadna praca po stronie klienta nie jest wykonywana bez jej utrwalenia.
  • Minusy : ostatnia czynność wykonywana przez użytkownika po utracie limitu czasu sesji.

4. Wyloguj użytkownika po zakończeniu sesji

może to mieć kilka podejść

  1. Zapytaj serwer „wygasła sesja” - to trochę haczyk 22 / kot Schrodingera, ponieważ samo pytanie do serwera przedłuża sesję (restartuje limit czasu),

    • W jaki sposób? Albo masz serwer, który obsługuje takie pytanie (nie znam żadnego, ale pochodzę z Jawy) lub możesz po prostu przechowywać tabelę identyfikatorów sesji i czas ostatniego dostępu ręcznie i zapytać serwer, przekazując sesję Identyfikator jako parametr zamiast pliku cookie, nie jestem pewien, czy jest to w ogóle możliwe, ale brzmi to niebezpiecznie, niepewnie i źle. Strona logowania, trwa po zalogowaniu
    • Plusy : Jeśli na serwerach istniała taka natywna obsługa, brzmi to jak czyste, uzasadnione pytanie (pytanie, czy użytkownik X nadal ma sesję, czy nie bez odnawiania jej, jeśli tak jest)
    • Wady : jeśli serwer go nie obsługuje (i ponownie, nie wiem, czy jakikolwiek serwer lub struktura ma taką funkcjonalność), wówczas obejście może potencjalnie wiązać się z dużym ryzykiem bezpieczeństwa.
  2. Jednym z obejść, które słyszałem, jest krótka sesja po stronie serwera i pingowanie po stronie klienta, które ma maksymalną liczbę pingów

    • W jaki sposób? Krótka sesja na serwerze, klient wysyła ping do każdej sesjiTimeOut / 2, ma maksymalną liczbę powtórzeń Y.
    • Plusy : rodzaj naprawia problem, szybki i brudny
    • Minusy : Czuje się jak włamanie, samodzielne zarządzanie odnawianiem sesji zamiast pozwalania temu serwerowi
  3. Zegar po stronie klienta

    • W jaki sposób? Posiadaj licznik czasu po stronie klienta i zsynchronizuj go z serwerem, uruchamiając go ponownie przy każdym żądaniu, aby był równy maksymalnemu limitowi czasu sesji serwera pomniejszonemu o dopełnianie, po tym, jak użytkownik nie wyśle ​​żadnego żądania do serwera, interfejs użytkownika pokazuje „sesje to zbliża się przerwa, czy chcesz kontynuować? ” (jak w bankowości internetowej)

    • Plusy : rozwiązuje problem

    • Minusy : nie mogę wymyślić żadnego z wyjątkiem potrzeby upewnienia się, że synchronizacja działa

Pytanie

Prawdopodobnie brakuje mi czegoś w powyższej analizie, mogę mieć jakieś głupie błędy i chciałbym, abyś pomógł je poprawić. Jakie inne rozwiązania mogę na to mieć?


Używam angular i django z tastypie, więc oto moje przemyślenia z tego punktu widzenia: 4.1: Klasa uwierzytelnienia używana dla wszystkich twoich zasobów może sprawdzić i porównać różnicę czasu między teraz a wartością pola „ostatniego dostępu” na twoim użytkowniku Model. 401 oznacza, że ​​czas jest dłuższy niż skonfigurowane ramy czasowe. 200 w przeciwnym razie i zaktualizuj pole „ostatni dostęp” za pomocą now. 4.2 brzmi jak świetny sposób na zabicie serwera i zwiększenie kosztów. 4.3 W Androidzie, gdy wracam do ekranu głównego, jestem prawie pewien, że proces został wstrzymany, co może również zakłócać działanie timera po stronie klienta.
airtonix

Odpowiedzi:


5

Myślę, że najczęstszym prostym rozwiązaniem jest ustawienie timera po stronie klienta, który wyświetla komunikat po upływie pewnej części normalnego okna limitu czasu, a następnie wymusza ich wylogowanie tuż przed wygaśnięciem sesji, jeśli nie podejmie żadnych działań.

Lokalne przechowywanie i automatyczne zapisywanie wprowadzają pewne problemy z transakcjami i tym, co naprawdę oznacza zapisany. Byłem przy wielu projektach, w których okazało się to większym problemem niż jest to warte, gdy baza użytkowników nie rozumie mechaniki stojącej za tym.

Nigdy nie można się wylogować tam, gdzie pozwalają na to przepisy, ale prowadzi to do błędów, w których nie radzisz sobie właściwie z tym, co się stanie, jeśli ktoś zostanie nieoczekiwanie wylogowany, a cała działalność państwowa staje się trochę intensywna w utrzymaniu, jeśli jest bardzo dużo do śledzenia „aktywny” użytkownik.


2

Jednym z obejść, jakie słyszałem, jest krótka sesja po stronie serwera i ping> utrzymywanie przy życiu klienta, który ma maksymalną liczbę

W jaki sposób? Krótka sesja na serwerze, klient pinguje każdą sesjęTime / 2, ma maks.> Ponownych prób Y. Zalety: Rodzaj naprawia problem, szybkie i brudne Wady: Czuje się jak włamanie, samodzielne zarządzanie odnawianiem sesji zamiast> pozwalanie serwerowi to zrobić

To moim zdaniem najlepsze rozwiązanie. Dlaczego uważasz to za „brudny hack”?

To sprawia, że ​​dokładnie to, co trzeba zrobić. Podczas gdy użytkownik pracuje z programem, sesja pozostanie otwarta.

Gdy użytkownik przestanie pracować z programem, sesja zostanie zamknięta.

Wystarczająco proste do wdrożenia.

Dokładnie to, co jest potrzebne, jeśli dobrze zrozumiałem pytanie.


Czasami brudne hacki to najlepsze rozwiązania :) dzięki. Zrozumiałeś pytanie doskonale
Eran Medan

2

Właśnie tworzę aplikację, która sobie z tym poradzi.

Zacząłem od utworzenia usługi RESTful przy użyciu Django, Guradian i Tastypie. Uwierzytelnia się tylko przy użyciu APIKEY, autoryzacja do obiektów jest obsługiwana przez Guardian.

Aplikacja django ma tylko jeden widok szablonu urlconf, który ładuje plik base.html ...

Po stronie klienta stworzyłem aplikację przy użyciu Angulara.

Jeśli chodzi o uwierzytelnianie, istnieje przechwytywacz http, który nasłuchuje odpowiedzi 401.

Po otrzymaniu 401 buforuje wychodzące żądanie i odpala zdarzenie „wymagane logowanie”. Może się to zdarzyć kilka razy.

Mam modalne wyskakujące okienko zawierające formularz logowania, który jest wyświetlany, gdy usłyszysz zdarzenie „wymagane logowanie”, i wykonuje logowanie, które zwraca zasób użytkownika (pakiet JSON), który również zawiera APIKEY.

Wszystkie buforowane żądania, które wcześniej powodowały odpowiedź 401, są odtwarzane z APIKEY teraz zawartym w nagłówku http autoryzacji.

Używam innej usługi / fabryki kątowej do zarządzania lokalnymi danymi JSON i tam przechowuję nazwę użytkownika i apikey.

Jedynym fragmentem układanki, który pozostaje do rozwiązania, jest sposób zabezpieczenia tych informacji i wymuszenia przekroczenia limitu czasu na te informacje.

Być może użyj znacznika czasu z ostatniego ważnego żądania HTTP.


W następstwie tego rozważałem dokonanie następującego porównania przy każdej kontroli uwierzytelnienia typu: bieżący czas> użytkownik.lastlogin_time + ustawienia.SESSION_TIMEOUT. następnie zwróć 401, jeśli jest prawdziwe. Każde prawidłowe uwierzytelnienie aktualizuje user.lastlogin_time do current_time.
airtonix

To całkiem miłe i jak myślałem o tym, jak sobie z tym poradzić.
oligofren

1

W moim przypadku używam czegoś podobnego do 4.1. Po tym, jak użytkownik zaloguje się bardzo lekki, sterowany kątowo AJAX, żądanie Json pojawia się w interfejsie API REST w ustalonych odstępach czasu względem serwera. Ze względu na wymagania bezpieczeństwa zastrzeżony interfejs użytkownika przewiduje, że serwer będzie utrzymywał sesję dla użytkownika, która przechowuje niektóre chronione informacje, szablony, dane itp. Po stronie serwera. Jest to nadal moja preferowana metoda z punktu widzenia bezpieczeństwa. W przypadku poufnych danych (nie tylko hashowanych haseł itp.) IMO przechowywanie ich po stronie klienta w lokalnej pamięci masowej itp. Stwarza większe ryzyko niż po stronie serwera (jestem pewien, że ktoś ze mną o tym dyskutuje). Firmy zewnętrzne używają tego samego interfejsu API podczas komunikacji z systemem, ale muszą wysyłać dane uwierzytelniające przy każdym żądaniu.

Sesja na serwerze ma maksymalny okres bezczynności, a silnik pamięci sesji jest zapisywany w pamięci (który ma również maksymalny okres, w którym sesja pamięci zostanie oznaczona jako wygasła). Czas życia musi być tylko dłuższy niż czas życia sesji, który jest abstrakcyjny w aplikacji (i nie musi być moim wiele). EG Sesja nie może wygasnąć, dopóki nie będzie bezczynna przez 48 godzin, o ile dotyczy to serwera, ale twój kod kontroluje rzeczywisty czas życia. Może to prowadzić do problemów z zasobami, jeśli ten czas życia jest zbyt długi, a zarządzanie sesjami jest kiepskie.

W moim przypadku różni użytkownicy mogą mieć różne limity czasu bezczynności sesji w zależności od ich ról w organizacji. Serwer nakłada maksymalne limity na czas trwania sesji, ale tak długo, jak limity zdefiniowane przez użytkownika są mniejsze niż te, działa dobrze. Gdy serwer wygaśnie sesję, jest to kwestia sporna, ponieważ proces wygaśnięcia sesji byłby już obsługiwany przez aplikację z wdziękiem. Jest to wymóg rodzaju aplikacji biznesowej, którą zbudowałem.

Gdy sesja użytkowników będzie bezczynna i znajdzie się w progu określonym przez aplikację, interfejs API poleci interfejsowi użytkownika wyświetlenie okna dialogowego odliczania (podobnie jak banki), a gdy znajdzie się w określonym przedziale czasu od wygaśnięcia, z wdziękiem wylogowuje użytkownika. Ta funkcja utrzymuje się w różnych oknach przeglądarki (ponieważ serwer jest pod kontrolą), a bezczynne zdarzenie w dowolnym oknie rozpocznie pełen wdzięku zegar i proces automatycznego wylogowania (i utrzyma je w synchronizacji).

Jeśli przypadkiem sesja wygasa w nieskromny sposób (sesje są zrzucane na memcached), następne żądanie, które wpłynie na serwer, powiadomi użytkownika i przeniesie je z powrotem do kwadratu (rzadko się zdarza, ale może).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.