Timeout-Behandlung für Benutzersitzungen in SaaS-Apps - Erörterung verschiedener Ansätze

11

Ich weiß, dass dies eine große Chance hat, als Duplikat markiert zu werden, konnte aber nicht genau das finden, wonach ich suche

Dies ist ein häufiges Problem, und ich bin sicher, dass es eine gut definierte Best-Practice-Lösung gibt

Hintergrund

  1. Eine einseitige SaaS-App verfügt über viele Drag & Drop-Funktionen. Der Benutzer kann über einen bestimmten Zeitraum ohne viel Serverkommunikation mit ihr interagieren

  2. Die Serversitzung enthält nur Benutzerobjekte, die ein nicht persistentes Sitzungscookie verwenden

  3. Die Sitzung läuft auf dem Server nach X Stunden ab

  4. Einige Dinge werden nur beim Anmelden geladen

Problem

  1. Der Benutzer arbeitet an der App. Wenn er fertig ist, meldet er sich nicht ab, sondern lässt den Browser geöffnet
  2. Der Benutzer kommt nach mehr als X Stunden zurück (Sitzung auf dem Server ist ungültig)
  3. Der Benutzer interagiert mit der App, ohne dass eine Serververbindung erforderlich ist (schleppt und löscht Dinge, Textänderungen ...).
  4. Erst bei der nächsten Serverinteraktion (nehmen wir an, es gibt keine automatische Speicherung) wird der Benutzer auf die Anmeldeseite geworfen und verliert einen Teil seiner Arbeit

Mögliche Lösungen

Hier sind einige Lösungen, die ich im Sinn habe, die ich gerne hören würde, wenn es andere gibt und wenn irgendetwas grundlegend falsch ist.

1. Melden Sie den Benutzer niemals ab

  • Wie? Halten Sie entweder eine lange Sitzung, ein dauerhaftes Cookie oder JavaScript-Ping "Keep Alive"
  • Vorteile : Der Benutzer muss sich um nichts kümmern, behebt das Problem für ihn
  • Nachteile : Nicht PCI-kompatibel, nicht sicher und erfordert Entwicklungsänderungen, z. B. Dinge, die nur bei der Benutzeranmeldung in die Sitzung geladen werden, müssen entweder in ein Pub-Untermodell verschoben werden (Ereignisänderungen abhören) oder ein Cache-Timeout aufweisen.

2. Lokaler Speicher

  • Wie? Verwenden Sie einen neuen lokalen Speicher, um den Status vorübergehend zu speichern, wenn Sie abgemeldet sind, um zur Anmeldeseite umzuleiten und nach dem Anmelden beizubehalten
  • Vorteile : Basis auch für die Unterstützung "offline arbeiten", nicht nur für die Behandlung des Sitzungszeitlimits
  • Nachteile : Schwieriger zu implementieren, Statuszusammenführung des Datenbaums erforderlich, nicht alle Browser unterstützen

3. Automatisch speichern

Jede Benutzeraktion, die das Modell ändert, sollte sofort bestehen bleiben (oder über eine Art clientseitige Warteschlange), z. B. wenn sie ein Kontrollkästchen aktiviert, ein Textfeld ändert oder etwas per Drag & Drop zieht, sobald sie fertig sind, bleiben die Änderungen bestehen.

  • Wie? Verwenden Sie ein MV ** -Framework (Backbone.js / Knockout.js / Ember.js / Angular.js usw.), um das Modell zu binden und Änderungen beizubehalten.
  • Vorteile : Scheint eine saubere Lösung zu sein. Die Sitzung ist aktiv, solange der Benutzer aktiv ist. Es wird keine clientseitige Arbeit ausgeführt, ohne sie beizubehalten.
  • Nachteile : Der letzte Aktionsbenutzer, der ausgeführt wird, nachdem ein Sitzungszeitlimit verloren gegangen ist.

4. Melden Sie den Benutzer nach Ablauf der Sitzung ab

Dies kann mehrere Ansätze haben

  1. Fragen Sie den Server "Sitzung abgelaufen" - dies ist ein kleiner Haken 22 / Schrödingers Katze, da die bloße Frage an den Server die Sitzung verlängert (das Timeout neu startet).

    • Wie? Entweder haben Sie einen Server, der solche Fragen unterstützt (ich kenne keine, aber ich komme aus Java), oder Sie können einfach eine Tabelle mit Sitzungs-IDs und der letzten Zugriffszeit manuell führen und den Server durch Übergeben der Sitzung fragen ID als Parameter anstelle des Cookies, ich bin nicht sicher, ob dies überhaupt möglich ist, aber es klingt gefährlich, unsicher und schlechtes Design, egal welche Anmeldeseite, bleibt bestehen, sobald Sie angemeldet sind
    • Vorteile : Wenn es eine solche native Unterstützung auf Servern gab, klingt dies nach einer sauberen, legitimen Frage (zu fragen, ob Benutzer X noch eine Sitzung hat oder nicht, ohne sie zu erneuern, wenn dies der Fall ist)
    • Nachteile : Wenn der Server dies nicht unterstützt (und ich weiß auch nicht, ob ein Server oder ein Framework über diese Funktionalität verfügt), birgt die Problemumgehung möglicherweise enorme Sicherheitsrisiken.
  2. Eine Problemumgehung, die ich gehört habe, ist eine kurze Sitzung auf der Serverseite und ein Ping auf der Clientseite mit einer maximalen Anzahl von Pings

    • Wie? Kurze Sitzung auf dem Server, Client pingt jede SitzungTimeOut / 2, hat maximale Wiederholungsversuche von Y.
    • Vorteile : Behebt das Problem schnell und schmutzig
    • Nachteile : Es fühlt sich wie ein Hack an, die Sitzungserneuerung selbst durchzuführen, anstatt den Server dies tun zu lassen
  3. Client-seitiger Timer

    • Wie? Haben Sie einen Timer auf der Clientseite und synchronisieren Sie ihn mit dem Server, indem Sie ihn bei jeder Anforderung neu starten, um dem maximalen Zeitlimit für Serversitzungen abzüglich einiger Auffüllungen zu entsprechen. Nachdem der Benutzer keine Anforderung an den Server gesendet hat, zeigt die Benutzeroberfläche an, dass "Sitzungen sind" kurz vor einer Auszeit, willst du weitermachen? " (wie Sie es beim Online-Banking getan haben)

    • Vorteile : Behebt das Problem

    • Nachteile : Ich kann mir nichts anderes vorstellen, als sicherzustellen, dass die Synchronisierung funktioniert

Die Frage

Ich vermisse wahrscheinlich etwas in der obigen Analyse, habe möglicherweise einige dumme Fehler und möchte, dass Ihre Hilfe sie korrigiert. Welche anderen Lösungen kann ich dafür haben?

Eran Medan
quelle
Ich verwende Angular und Django mit Tastypie, daher hier meine Gedanken aus dieser Sicht: 4.1: Die für alle Ihre Ressourcen verwendete Authentifizierungsklasse kann den Zeitunterschied zwischen jetzt und dem Wert des Felds "Letzter Zugriff" auf Ihrem Benutzer überprüfen und vergleichen Modell. 401 ist die Zeit größer als der konfigurierte Zeitrahmen. 200 andernfalls und aktualisieren Sie das Feld 'Letzter Zugriff' mit now. 4.2 klingt nach einer großartigen Möglichkeit, Ihren Server zu töten und die Kosten zu erhöhen. 4.3 Unter Android bin ich mir ziemlich sicher, dass der Vorgang angehalten wird, wenn Sie zum Startbildschirm zurückkehren. Dies kann auch den Timer auf der Clientseite beeinträchtigen.
Airtonix

Antworten:

5

Ich denke, die häufigste einfache Lösung besteht darin, auf der Client-Seite einen Timer festzulegen, der eine Nachricht anzeigt, nachdem ein bestimmter Teil des normalen Zeitlimitfensters verstrichen ist, und diese dann zwangsweise abzumelden, bevor die Sitzung ohnehin abläuft, wenn sie keine Maßnahmen ergreifen.

Lokale Speicherung und automatische Speicherung führen zu einigen Problemen bei Transaktionen und was das Speichern wirklich bedeutet. Ich war an einigen Projekten beteiligt, bei denen sich herausstellte, dass dies mehr Probleme bereitet als es wert ist, wenn die Benutzerbasis die dahinter stehenden Mechanismen nicht versteht.

Das Abmelden kann niemals erfolgen, wenn die Vorschriften dies zulassen. Es führt jedoch zu Fehlern, bei denen Sie nicht richtig damit umgehen, was passiert, wenn jemand unerwartet abgemeldet wird, und das gesamte staatliche Geschäft wird ein wenig intensiver zu warten, wenn es sehr viel zu verfolgen gibt ein "aktiver" Benutzer.

Rechnung
quelle
2

Eine Problemumgehung, die ich gehört habe, ist eine kurze Sitzung auf der Serverseite und ein Ping auf der Clientseite mit maximaler Anzahl

Wie? Kurze Sitzung auf dem Server, Client pingt jede SitzungTime / 2, hat maximal> Wiederholungsversuche von Y. Vorteile: Behebt das Problem, schnell und schmutzig Nachteile: Fühlt sich wie ein Hack an, der die Sitzungserneuerung selbst durchführt, anstatt den Server dies tun zu lassen

Dies ist meiner Meinung nach die beste Lösung. Warum halten Sie es für einen "schmutzigen Hack"?

Es macht genau das, was getan werden muss. Während der Benutzer mit dem Programm arbeitet, bleibt die Sitzung geöffnet.

Nachdem der Benutzer die Arbeit mit dem Programm beendet hat, wird die Sitzung geschlossen.

Einfach genug, um implementiert zu werden.

Genau das, was benötigt wird, wenn ich die Frage richtig verstanden habe.

Johnfound
quelle
Manchmal sind die Dirty Hacks die besten Lösungen :) Danke. Sie haben die Frage vollkommen richtig verstanden
Eran Medan
2

Ich erstelle gerade eine Anwendung, die sich damit befasst.

Ich begann damit, einen RESTful-Service mit Django, Guradian und Tastypie zu erstellen. Die Authentifizierung erfolgt nur mit APIKEY. Die Autorisierung für Objekte wird von Guardian übernommen.

Die Django App hat nur eine Vorlagenansicht urlconf, die die base.html lädt, die ...

Auf der Client-Seite habe ich eine Anwendung mit Angular erstellt.

In Bezug auf die Authentifizierung gibt es einen http-auth-Interceptor, der auf 401 Antworten wartet.

Wenn ein 401 empfangen wird, puffert es die ausgehende Anforderung und löst ein Ereignis aus, das "Anmeldung erforderlich" ist. Dies kann mehrmals vorkommen.

Ich habe ein modales Popup mit einem Anmeldeformular, das angezeigt wird, wenn das Ereignis "Anmeldung erforderlich" zu hören ist, und es führt eine Anmeldung durch, die eine Benutzerressource (ein JSON-Bundle) zurückgibt, die auch den APIKEY enthalten würde.

Alle gepufferten Anforderungen, die zuvor zu einer 401-Antwort geführt haben, werden mit dem APIKEY wiedergegeben, der jetzt im HTTP-Header für die Autorisierung enthalten ist.

Ich verwende einen anderen eckigen Dienst / eine andere Fabrik, um lokale Speicher-JSON-Daten zu verwalten, und dort speichere ich den Benutzernamen und apikey.

Das einzige noch zu lösende Puzzleteil ist, wie diese Informationen gesichert und eine Zeitüberschreitung für diese Informationen erzwungen werden.

Verwenden Sie möglicherweise eine Zeitstempelprüfung der letzten gültigen http-Anforderung.

airtonix
quelle
Als Folge davon habe ich erwogen, bei jeder Prüfung der Tastypie-Authentifizierung den folgenden Vergleich durchzuführen: current_time> user.lastlogin_time + settings.SESSION_TIMEOUT. Geben Sie dann 401 zurück, wenn true. Jede gültige Authentifizierung aktualisiert die user.lastlogin_time auf current_time.
Airtonix
Das ist ganz nett und wie ich auch darüber nachgedacht habe, damit umzugehen.
Oligofren
1

In meinem Fall verwende ich etwas Ähnliches wie 4.1. Nachdem sich der Benutzer angemeldet hat, erfolgt eine sehr leichte, winkelgesteuerte AJAX-JSON-Anforderung an die REST-API in festgelegten Intervallen für den Server. Aufgrund von Sicherheitsanforderungen geht die proprietäre Benutzeroberfläche davon aus, dass der Server eine Sitzung für den Benutzer aufrechterhält, in der einige geschützte Informationen, Vorlagen, Daten usw. auf der Serverseite gespeichert werden. Dies ist aus Sicherheitsgründen immer noch meine bevorzugte Methode. Beim Umgang mit vertraulichen Daten (nicht nur gehashten Passwörtern und dergleichen) stellt die IMO-Speicherung auf der Clientseite im lokalen Speicher usw. ein höheres Risiko dar als auf der Serverseite (ich bin sicher, dass jemand dies mit mir diskutieren würde). Dritte verwenden bei der Kommunikation mit dem System dieselbe API, müssen jedoch bei jeder Anforderung Authentifizierungsdaten senden.

Auf die Sitzung auf dem Server wird eine maximale Leerlauflebensdauer angewendet, und die Sitzungsspeicher-Engine wird zwischengespeichert (wobei auch eine maximale Lebensdauer angewendet wird, zu welchem ​​Zeitpunkt die Speichersitzung als abgelaufen markiert wird). Die Lebensdauer muss nur größer sein als die Sitzungslebensdauer, die Sie in Ihrer Anwendung abstrahieren (und muss nicht meine sein). EG Die Sitzung läuft möglicherweise erst ab, wenn sie 48 Stunden lang inaktiv war, sofern der Server betroffen ist. Ihr Code steuert jedoch die tatsächliche Lebensdauer. Dies kann zu Ressourcenproblemen führen, wenn diese Lebensdauer zu lang ist und Sie die Sitzungen schlecht verwalten.

In meinem Fall können unterschiedliche Benutzer je nach ihren Rollen innerhalb der Organisation unterschiedliche Sitzungsleerzeiten haben. Der Server legt maximale Grenzwerte für die Sitzungslebensdauer fest. Solange die benutzerdefinierten Grenzwerte jedoch unter diesen liegen, funktioniert dies einwandfrei. Sobald der Server die Sitzung abläuft, ist dies ein strittiges Problem, da der Ablauf der Sitzung bereits ordnungsgemäß von der Anwendung behandelt worden wäre. Dies ist eine Anforderung für die Art von Geschäftsanwendung, die ich erstellt habe.

Sobald die Benutzersitzung inaktiv war und sich innerhalb eines von der Anwendung festgelegten Schwellenwerts befindet, weist die API die Benutzeroberfläche an, einen Countdown-Dialog anzuzeigen (wie dies bei den Banken der Fall ist), und sobald sie sich innerhalb eines bestimmten Zeitabstands vom Ablauf ordnungsgemäß befindet meldet den Benutzer ab. Diese Funktionalität bleibt in allen Browserfenstern erhalten (da der Server die Kontrolle hat), und ein Leerlaufereignis in einem beliebigen Fenster startet den ordnungsgemäßen Timer und den automatisierten Abmeldevorgang (und hält sie synchron).

Wenn die Sitzung zufällig auf unansehnliche Weise abläuft (die Sitzungen werden im Memcached gespeichert), benachrichtigt die nächste Anforderung, die sich auf den Server auswirkt, den Benutzer und verschiebt sie zurück auf den ersten Platz (kommt selten vor, kann aber).

Chris
quelle