Gestione del timeout della sessione utente nelle app SaaS - discutendo diversi approcci


11

So che ha grandi probabilità di essere contrassegnato come duplicato, ma non sono riuscito a trovare esattamente quello che sto cercando

Questo è un problema comune e sono sicuro che abbia qualche soluzione di best practice ben definita

sfondo

  1. Un'app SaaS a pagina singola, ha un sacco di trascinamento della selezione, l'utente può interagire con essa senza molta comunicazione del server per periodi di tempo

  2. La sessione del server contiene solo l'oggetto utente, utilizzando un cookie di sessione non persistente

  3. La sessione scade sul server dopo X ore

  4. Alcune cose vengono caricate solo durante l'accesso

Problema

  1. L'utente lavora sull'app, al termine, l'utente non si disconnette, mantiene il browser aperto
  2. L'utente ritorna dopo più di X ore (la sessione non è valida sul server)
  3. L'utente interagisce con l'app senza bisogno di una connessione al server (trascina e rilascia cose, modifiche di testo ...)
  4. Solo alla successiva interazione del server (supponiamo che non ci sia salvataggio automatico) l'utente viene lanciato nella pagina di accesso e perde parte del suo lavoro

Possibili soluzioni

Ecco alcune soluzioni che ho in mente, vorrei sapere se ce ne sono altre e se c'è qualcosa di fondamentalmente sbagliato in ognuna di esse.

1. Non disconnettere mai l'utente

  • Come? o mantenere una sessione lunga, mantenere un cookie persistente o ping "keep alive" javaScript
  • Pro : l'utente non deve preoccuparsi di nulla, risolve il problema per loro
  • Contro : non conforme a PCI, non sicuro e necessita di modifiche di sviluppo, ad es. Le cose caricate nella sessione solo al momento dell'accesso dell'utente devono spostarsi in un sotto-modello pub (ascoltare le modifiche agli eventi) o avere il timeout della cache.

2. Archiviazione locale

  • Come? utilizzare la nuova memoria locale per memorizzare temporaneamente lo stato se si è disconnessi, reindirizzare alla pagina di accesso, persistere una volta effettuato l'accesso
  • Pro : anche la base per il supporto "lavoro offline", non solo per gestire il timeout della sessione
  • Contro : più difficile da implementare, è necessario eseguire l'unione dello stato dell'albero dei dati, non tutti i browser supportano

3. Salvataggio automatico

Ogni azione dell'utente che modifica il modello, dovrebbe persistere immediatamente (o tramite una sorta di coda lato client), ad esempio se spuntano una casella di controllo, cambiano un campo di testo o trascinano qualcosa, una volta che hanno fatto, persistono le modifiche.

  • Come? Utilizzare un framework MV ** (Backbone.js / Knockout.js / Ember.js / Angular.js ecc.) Per associare il modello e persistere sulle modifiche.
  • Pro : sembra una soluzione pulita, la sessione è attiva fintanto che l'utente è attivo, nessun lavoro sul lato client viene eseguito senza persistere.
  • Contro : l'ultima azione eseguita dall'utente dopo la perdita di un timeout della sessione.

4. Disconnettersi dopo la scadenza della sessione

questo può avere diversi approcci

  1. Chiedi al server "la sessione è scaduta" - questo è un po 'un problema 22 / Il gatto di Schrodinger, poiché la semplice domanda al server estende la sessione (riavvia il timeout),

    • Come? O hai un server che supporta tale domanda (non ne conosco nessuno, ma vengo da Java Land) oppure, si può semplicemente tenere una tabella di ID sessione e l'ultimo tempo di accesso manualmente e chiedere al server passando la sessione ID come parametro invece del cookie, non sono sicuro che ciò sia possibile, ma sembra pericoloso, insicuro e di cattiva progettazione in qualunque pagina.login, persiste una volta effettuato l'accesso
    • Pro : se c'era un tale supporto nativo nei server, sembra una domanda chiara e legittima (chiedere se l'utente X ha ancora una sessione o meno senza rinnovarla se lo fa)
    • Contro : se il server non lo supporta (e di nuovo, non so se nessun server o framework abbia questa funzionalità), la soluzione alternativa presenta potenzialmente enormi rischi per la sicurezza.
  2. Una soluzione alternativa che ho sentito è una breve sessione sul lato server e un ping sul lato client attivo, con un numero massimo di ping

    • Come? Breve sessione sul server, il client esegue il ping di ogni sessione TimeOut / 2, ha un numero massimo di tentativi di Y.
    • Pro : tipo di risolve il problema, veloce e sporco
    • Contro : sembra un trucco, gestire da soli il rinnovo della sessione invece di lasciare che il server lo faccia
  3. Timer lato client

    • Come? Avere un timer sul lato client e sincronizzarlo con quello del server riavviandolo su ogni richiesta in modo che sia uguale al timeout massimo della sessione del server meno un po 'di riempimento, dopo che l'utente non ha inviato alcuna richiesta al server, l'interfaccia utente mostra che "le sessioni sono sta per scadere, vuoi continuare? " (come hai fatto con l'online banking)

    • Pro : risolve il problema

    • Contro : non riesco a pensare a nessuno, tranne la necessità di assicurarsi che la sincronizzazione funzioni

La domanda

Probabilmente mi manca qualcosa nell'analisi di cui sopra, potrebbe avere degli errori sciocchi e vorrei che il tuo aiuto li correggesse. Quali altre soluzioni posso avere per questo?


Uso angular e django con tastypie, quindi ecco i miei pensieri da quel punto di vista: 4.1: la classe di autenticazione utilizzata per tutte le tue risorse potrebbe controllare e confrontare la differenza di tempo tra ora e il valore del campo "ultimo accesso" sul tuo utente modello. 401 è il tempo è maggiore del periodo di tempo configurato. 200 altrimenti e aggiorna il campo "ultimo accesso" con now. 4.2 sembra un ottimo modo per uccidere il tuo server e aumentare i costi 4.3 Su Android, quando torni alla schermata principale sono abbastanza sicuro che il processo sia sospeso e che potrebbe anche interferire con il timer del tuo client.
airtonix,

Risposte:


5

Penso che la soluzione più comune sia quella di impostare un timer sull'estremità del client che mostri un messaggio dopo che è passata una certa parte della normale finestra di timeout, quindi li disconnette forzatamente prima che la sessione scada comunque se non eseguono alcuna azione.

L'archiviazione locale e il salvataggio automatico introducono alcuni problemi con le transazioni e ciò che significa veramente salvare. Ho partecipato a diversi progetti in cui questo si è rivelato essere più un problema di quanto non valga la pena quando la base di utenti non capisce i meccanismi alla base.

La disconnessione non può mai essere eseguita laddove le normative lo consentano, ma ti porta a errori in cui non gestisci correttamente ciò che accade se qualcuno viene disconnesso inaspettatamente e tutto il settore statale diventa un po 'intensivo da mantenere se c'è molto su cui tracciare un utente "attivo".


2

Una soluzione alternativa che ho sentito è una breve sessione sul lato server e un ping sul lato client keep> alive, che ha un numero massimo di

Come? Breve sessione sul server, il client esegue il ping di ogni sessione Time / 2, presenta un numero massimo di> tentativi di Y. Pro: tipo di risoluzione del problema, veloce e sporco Contro: si sente come un hack, gestire il rinnovo della sessione da soli invece di> lasciare che il server lo faccia

Questa è secondo me la soluzione migliore. Perché lo consideri un "trucco sporco"?

Fa esattamente ciò che deve essere fatto. Mentre l'utente lavora con il programma, la sessione rimarrà aperta.

Dopo che l'utente ha smesso di lavorare con il programma, la sessione verrà chiusa.

Abbastanza semplice da implementare.

Esattamente quello che serve, se ho capito bene la domanda.


A volte gli hack sporchi sono le migliori soluzioni :) grazie. Hai capito perfettamente la domanda
Eran Medan,

2

In realtà sto creando un'applicazione che si occupa di questo.

Ho iniziato creando un servizio RESTful usando Django, Guradian e Tastypie. Si autentica utilizzando solo APIKEY, l'autorizzazione agli oggetti è gestita da Guardian.

L'app django ha solo una vista modello urlconf che carica la base.html che è ...

Sul lato client ho creato un'applicazione usando Angular.

Per quanto riguarda l'autenticazione, esiste un intercettore http-auth che ascolta 401 risposte.

Quando viene ricevuto un 401, esso respinge la richiesta in uscita e genera un evento "login richiesto". Questo potrebbe accadere più volte.

Ho un popup modale contenente un modulo di accesso che viene presentato quando viene ascoltato l'evento "login richiesto", ed esegue un login che restituisce una risorsa utente (un bundle JSON) che conterrebbe anche l'APIKEY.

Tutte le richieste memorizzate in buffer che in precedenza avevano prodotto una risposta 401 vengono riprodotte con l'APIKEY ora incluso nell'intestazione http di autorizzazione.

Uso un altro servizio / fabbrica angolare per gestire i dati json localstorage, ed è lì che memorizzo il nome utente e apikey.

L'unico pezzo del puzzle rimasto da risolvere è come proteggere tali informazioni e come imporre un timeout su tali informazioni.

Forse utilizzare un controllo data / ora dall'ultima richiesta http valida.


Come follow-up su questo, ho preso in considerazione la possibilità di fare il seguente confronto su ogni controllo di autenticazione tastypie: current_time> user.lastlogin_time + settings.SESSION_TIMEOUT. quindi restituire 401 se vero. Ogni autenticazione valida aggiorna user.lastlogin_time a current_time.
airtonix,

Questo è abbastanza carino e come ho pensato anche di gestirlo.
Oligofren,

1

Nel mio caso, sto usando qualcosa di simile a 4.1. Dopo che l'utente accede a una richiesta json AJAX angolare molto leggera, si verifica l'API REST a intervalli prestabiliti rispetto al server. A causa dei requisiti di sicurezza, l'interfaccia utente proprietaria anticipa che il server manterrà una sessione per l'utente che memorizza alcune informazioni protette, modelli, dati, ecc. Sul lato server. Questo è ancora il mio metodo preferito dal punto di vista della sicurezza. Quando si ha a che fare con dati sensibili (non solo password con hash e simili), l'IMO che lo memorizza sul lato client nell'archiviazione locale, ecc. Comporta un rischio maggiore rispetto al lato server (sono sicuro che qualcuno ne discuterà con me). Le terze parti utilizzano la stessa API durante le comunicazioni con il sistema, ma devono inviare credenziali di autenticazione ad ogni richiesta.

Alla sessione sul server è applicata una durata inattiva massima e il motore di archiviazione della sessione è memcached (che ha anche una durata massima applicata a quel punto la sessione di memoria verrà contrassegnata come scaduta). La durata non deve essere superiore alla durata della sessione astratta nella tua applicazione (e non deve essere la mia parte). Ad esempio, la sessione potrebbe non scadere fino a quando non è stata inattiva per 48 ore per quanto riguarda il server, ma il codice controlla la durata effettiva. Ciò potrebbe comportare problemi di risorse se quella durata è troppo grande e si fa un cattivo lavoro nella gestione delle sessioni.

Nel mio caso, diversi utenti possono avere diversi timeout di inattività della sessione in base ai loro ruoli all'interno dell'organizzazione. Il server pone limiti massimi alla durata della sessione ma fintanto che i limiti definiti dall'utente sono inferiori a quelli, funziona perfettamente. Una volta che il server ha scaduto la sessione, si tratta di un problema controverso poiché il processo di scadenza della sessione sarebbe già stato gestito dall'applicazione con garbo. Questo è un requisito per il tipo di applicazione aziendale che ho creato.

Una volta che la sessione degli utenti è stata inattiva e rientra in una soglia specificata dall'applicazione, l'API indicherà all'interfaccia utente di visualizzare una finestra di dialogo per il conto alla rovescia (come fanno le banche) e, una volta che si trova entro un determinato margine di distanza dalla scadenza, lo esegue correttamente disconnette l'utente. Questa funzionalità persiste in tutte le finestre del browser (poiché il server ha il controllo) e un evento inattivo su qualsiasi finestra avvierà il timer grazioso e il processo di disconnessione automatico (e li manterrà sincronizzati).

Se per caso la sessione scade in modo ingrato (le sessioni vengono scaricate su memcached), la successiva richiesta che incide sul server avviserà l'utente e li riporterà al punto di partenza (accade raramente, ma può).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.