Wie verwalten Sie Sitzungen, wenn REST-Anwendungen zustandslos sein sollen?


536

Ich brauche eine Klarstellung. Ich habe über REST gelesen und RESTful-Anwendungen erstellt. Laut Wikipedia wird REST selbst als repräsentativer Staatstransfer definiert . Ich verstehe daher nicht all dieses staatenlose Gobbledeygook , das jeder immer wieder ausspuckt.

Aus Wikipedia:

Zu einem bestimmten Zeitpunkt kann sich ein Client entweder im Übergang zwischen Anwendungsstatus oder "in Ruhe" befinden. Ein Client in einem Ruhezustand kann mit seinem Benutzer interagieren, erzeugt jedoch keine Last und verbraucht keinen Speicher pro Client auf den Servern oder im Netzwerk.

Sagen sie nur, dass sie keinen Datenspeicher auf Sitzungs- / Anwendungsebene verwenden?

Ich verstehe, dass ein Ziel von REST darin besteht, den URI-Zugriff konsistent und verfügbar zu machen, anstatt beispielsweise Paging-Anforderungen in Posts zu verbergen und die Seitenzahl einer Anforderung zu einem Teil des GET-URI zu machen. Für mich ergibt das Sinn. Aber es scheint, als würde man einfach über Bord gehen und sagen, dass keine Daten pro Client (Sitzungsdaten) jemals serverseitig gespeichert werden sollten.

Was wäre, wenn ich eine Warteschlange mit Nachrichten hätte und mein Benutzer die Nachrichten lesen wollte, aber während er sie las, bestimmte Absendernachrichten für die Dauer seiner Sitzung blockieren wollte? Wäre es nicht sinnvoll, dies an einem Ort auf der Serverseite zu speichern und den Server nur Nachrichten (oder Nachrichten-IDs) senden zu lassen, die nicht vom Benutzer blockiert wurden?

Muss ich wirklich die gesamte Liste der Absender von Nachrichten senden, um sie jedes Mal zu blockieren, wenn ich die neue Nachrichtenliste anfordere? Die für mich relevante Nachrichtenliste wäre / sollte nicht einmal eine öffentlich verfügbare Ressource sein.

Wieder nur versuchen, dies zu verstehen. Jemand bitte klären.


Aktualisieren:

Ich habe einen Stapelüberlauf Frage gefunden , die eine Antwort hat , die nicht ganz mir den ganzen Weg dorthin gelangen: Wie Zustand in REST verwalten , die besagt , dass der Client Zustand, der wichtig ist , sollten alle auf jede Anfrage übertragen werden .... Ugg .. scheint viel Aufwand ... Ist das richtig?


2
@ S.Lott: Ich denke nicht, dass es absichtlich irreführend ist. Ich denke, es ist ein Missverständnis wegen der verwirrenden Terminologie.
NUR MEINE RICHTIGE MEINUNG

2
@NUR MEINE RICHTIGE MEINUNG: Interessante Vermutung. Ich konnte so etwas selbst nicht glauben, da es offensichtlich ist, dass "zustandslos" bedeutet, dass das REST-Protokoll selbst zustandslos ist; Dies sagt nichts über den zugrunde liegenden Anwendungsstatus aus und aktualisiert ihn mit PUT-, POST- und DELETE-Anforderungen.
S.Lott

@ S.Lott: Das HTTP-Protokoll selbst ist zustandslos. Nach dem, was wir unten besprochen haben, ist REST eine Sichtweise, wie Sie Ihre App erstellen können, ohne dass der Webserver den Sitzungsstatus verarbeitet (im Gegensatz zu anderen Arten von Status in Dingen wie der Datenbank). Ich glaube nicht einmal REST war ein Protokoll, sondern ein Blick auf wie das HTTP - Protokoll zu verwenden. Ich dachte, Sie haben klargestellt, dass es darum geht, Ihre Anwendung maßstabsgetreu zu erstellen, indem die Clientseite alle clientspezifischen Sitzungsdaten speichert und URI-Zugriffe so idempotent wie möglich macht, außer dort, wo sie nicht sein sollten. Vielleicht nicht ... :(
Zak

1
"Vielleicht nicht ..." Was bedeutet das? Hast du eine neue frage Fühlen Sie sich frei, SO danach zu suchen. Wenn es hier nicht existiert, dann fragen Sie es.
S.Lott

Hat jemand Webber, Parastatidis und Robinsons ReST in der Praxis gelesen (oder auf andere Weise das Beispiel seines Restbucks gesehen)? Die folgenden Antworten sind sinnvoll, aber die Kaffeebestellungen im Restbucks-Beispiel beziehen sich sicherlich auf einen Kunden. Die Anzahl der Bestellungen skaliert mit der Anzahl der Kunden. Wo liegt die Grenze zwischen dem Clientstatus und einer Ressource?
Rikki

Antworten:


340

Staatenlosigkeit bedeutet, dass jede HTTP-Anforderung vollständig isoliert erfolgt. Wenn der Client eine HTTP-Anfrage stellt, enthält er alle Informationen, die der Server benötigt, um diese Anfrage zu erfüllen. Der Server ist niemals auf Informationen aus früheren Anforderungen angewiesen. Wenn diese Informationen wichtig wären, müsste der Kunde sie in einer späteren Anfrage erneut senden. Staatenlosigkeit bringt auch neue Funktionen. Es ist einfacher, eine zustandslose Anwendung auf Servern mit Lastenausgleich zu verteilen. Eine zustandslose Anwendung ist auch einfach zwischenzuspeichern.

Es gibt tatsächlich zwei Arten von Staaten. Anwendungsstatus, der sich auf dem Client befindet, und Ressourcenstatus, der sich auf dem Server befindet.

Ein Webdienst muss sich nur um Ihren Anwendungsstatus kümmern, wenn Sie tatsächlich eine Anfrage stellen. Den Rest der Zeit weiß es nicht einmal, dass du existierst. Dies bedeutet, dass ein Client bei jeder Anforderung alle Anwendungsstatus enthalten muss, die der Server zur Verarbeitung benötigt.

Der Ressourcenstatus ist für jeden Client gleich und der richtige Platz befindet sich auf dem Server. Wenn Sie ein Bild auf einen Server hochladen, erstellen Sie eine neue Ressource: Das neue Bild hat einen eigenen URI und kann das Ziel zukünftiger Anforderungen sein. Sie können diese Ressource über HTTP abrufen, ändern und löschen.

Ich hoffe, dies hilft zu unterscheiden, was Staatenlosigkeit und verschiedene Zustände bedeuten.


4
Bedeutet dies, dass der Client jedes Mal, wenn eine Anfrage gesendet wird, seinen Benutzer / sein Passwort zur Authentifizierung senden sollte? Weil ich denke, dass das Speichern einer Sitzung, selbst wenn sie sich auf einer gemeinsam genutzten No-SQL-Datenbank aller Server befindet, nicht zustandslos ist, oder?
Carlos Navarro Astiasarán

1
@ CarlosNavarroAstiasarán Es gibt verschiedene Techniken für den Umgang mit zustandsloser Authentifizierung. Google JWT zum Beispiel.
Geoidesic

1
@geoidesic: "Da JSON-Web-Token zustandslos sind, gibt es keine Möglichkeit, sie ungültig zu machen, ohne den Serverstatus zu speichern, wodurch der Vorteil zustandsloser Token zunichte gemacht wird." WIkipedia
ulatekh

@ulatekh Das ist eine grobe Falschdarstellung dessen, was Sie mit den Token machen können. Es ist ganz einfach, eine genehmigte ID zusammen mit dem Token zu speichern und nur Token mit einer genehmigten ID als Anspruch zu akzeptieren. Staatenlos bedeutet nicht, dass Sie nichts in einer Datenbank haben können. Im Wesentlichen speichern Sie eine ID in der Datenbank, die mit derselben ID im Token übereinstimmen muss. Um das Token zu widerrufen, entfernen Sie die ID aus der Datenbank. Im Dienst selbst wird kein Status gespeichert. Oder noch besser, Sie speichern den Vorzeichenschlüssel beim Benutzer in der Datenbank und widerrufen den Schlüssel.
Andrew T Finnell

@AndrewTFinnell: Wenn Sie die genehmigte ID auf dem Server speichern müssen, muss sie auf allen potenziellen Servern gespeichert werden, die die REST-Anmeldung verarbeiten können. Dies kann zu einem hohen Serverstatus in einer massiv parallelen Webserver-Architektur führen.
ulatekh

491

Die grundlegende Erklärung lautet:

Kein Client-Sitzungsstatus auf dem Server.

Mit zustandslos bedeutet dies, dass der Server keinen Status über die Clientsitzung auf der Serverseite speichert .

Die Client-Sitzung wird auf dem Client gespeichert. Der Server ist zustandslos. Dies bedeutet, dass jeder Server jeden Client jederzeit bedienen kann. Es gibt keine Sitzungsaffinität oder Sticky-Sitzungen . Die relevanten Sitzungsinformationen werden auf dem Client gespeichert und bei Bedarf an den Server übergeben.

Dies schließt nicht aus, dass andere Dienste, mit denen der Webserver spricht, den Status von Geschäftsobjekten wie Einkaufswagen beibehalten, nur nicht den aktuellen Anwendungs- / Sitzungsstatus des Clients.

Der Anwendungsstatus des Clients sollte niemals auf dem Server gespeichert, sondern vom Client an jeden Ort weitergegeben werden, der ihn benötigt.

Von dort kommt der ST in REST , State Transfer . Sie übertragen den Status, anstatt ihn vom Server speichern zu lassen. Dies ist die einzige Möglichkeit, auf Millionen von gleichzeitigen Benutzern zu skalieren. Wenn auch aus keinem anderen Grund als weil Millionen von Sitzungen Millionen von Sitzungen sind.

Die Last der Sitzungsverwaltung wird auf alle Clients verteilt, die Clients speichern ihren Sitzungsstatus und die Server können viele Größenordnungen oder mehr Clients zustandslos bedienen.

Selbst für einen Dienst, von dem Sie glauben, dass er nur in Zehntausenden von gleichzeitigen Benutzern benötigt wird, sollten Sie Ihren Dienst zustandslos machen. Zehntausende sind immer noch Zehntausende, und damit sind Zeit- und Raumkosten verbunden.

Statuslos ist die Funktionsweise des HTTP-Protokolls und des Webs im Allgemeinen und stellt eine insgesamt einfachere Implementierung dar. Sie haben einen einzelnen Codepfad anstelle einer Reihe serverseitiger Logik, um eine Reihe von Sitzungsstatus aufrechtzuerhalten.

Es gibt einige sehr grundlegende Implementierungsprinzipien:

Dies sind Prinzipien, keine Implementierungen. Wie Sie diese Prinzipien erfüllen, kann variieren.

Zusammenfassend sind die fünf Hauptprinzipien :

  1. Geben Sie jedem "Ding" einen Ausweis
  2. Dinge miteinander verbinden
  3. Verwenden Sie Standardmethoden
  4. Ressourcen mit mehreren Darstellungen
  5. Staatenlos kommunizieren

In der REST- Dissertation gibt es nichts über Authentifizierung oder Autorisierung .

Weil es nichts anderes gibt, als eine REST-fähige Anfrage von einer nicht authentifizierten zu authentifizieren. Die Authentifizierung ist für die RESTful-Diskussion irrelevant.

Es ist zu weit gefasst zu erklären, wie Sie eine zustandslose Anwendung für Ihre speziellen Anforderungen erstellen für Stackoverflow.

Die Implementierung der Authentifizierung und Autorisierung in Bezug auf REST ist noch zu weit gefasst, und verschiedene Implementierungsansätze werden im Internet im Allgemeinen ausführlich erläutert.

Kommentare, die um Hilfe / Informationen zu diesem Thema bitten, sollten nur als nicht mehr benötigt gekennzeichnet werden .


22
Das scheint eine ziemlich kühne Aussage zu sein, dass dies die einzige Möglichkeit ist , auf Millionen von Benutzern zu skalieren. Warum können serverseitige Sitzungen nicht nur ein weiterer Dienst sein?
Zak

27
@Zak: Weil Millionen von Sitzungen Millionen von Sitzungen sind. Es geht darum, den Aufwand für die gesamte Sitzungsverwaltung zu vermeiden.
S.Lott

91
es ist keine Kühnheit, es ist Erfahrung

21
Nichts in meiner Antwort impliziert eine Lösung, die auf dem Datenbankzugriff bei jeder Anfrage basiert. Wenn Sie der Meinung sind, dass dies der Fall ist, ist es für Sie ein Fehler, die Authentifizierung und Autorisierung in dieser Größenordnung zu verstehen. Die Authentifizierung kann im Status impliziert sein. Glauben Sie, dass Facebook bei jeder Anforderung seiner REST-API einen "Datenbankzugriff" ausführt? Oder Google für diese Angelegenheit? Hinweis: Nein

6
Wenn ich also den Benutzerstatus in einem verteilten Cache speichere, z. B. Memcache, und mein Webserver jetzt keinen Status mehr speichern muss, sondern den Status aus dem Memcache abruft, kann ich diese Anwendung als zustandslos betrachten?
Jaskey

76

Sagen sie nur, dass sie keinen Datenspeicher auf Sitzungs- / Anwendungsebene verwenden?

Nein, das sagen sie nicht auf triviale Weise.

Sie sagen, definieren Sie keine "Sitzung". Logge dich nicht ein. Melden Sie sich nicht ab. Geben Sie die Anmeldeinformationen für die Anforderung an. Jede Anfrage steht für sich.

Sie haben noch Datenspeicher. Sie haben noch Authentifizierung und Autorisierung. Sie verschwenden einfach keine Zeit damit, Sitzungen einzurichten und den Sitzungsstatus beizubehalten.

Der Punkt ist, dass jede Anforderung (a) völlig alleine steht und (b) ohne tatsächliche Arbeit trivial auf eine riesige parallele Serverfarm verteilt werden kann. Apache oder Squid können RESTful-Anfragen blind und erfolgreich weitergeben.

Was wäre, wenn ich eine Warteschlange mit Nachrichten hätte und mein Benutzer die Nachrichten lesen wollte, aber während er sie las, bestimmte Absendernachrichten für die Dauer seiner Sitzung blockieren wollte?

Wenn der Benutzer einen Filter wünscht, geben Sie den Filter einfach bei jeder Anforderung an.

Wäre es nicht sinnvoll, ... den Server nur Nachrichten (oder Nachrichten-IDs) senden zu lassen, die nicht vom Benutzer blockiert wurden?

Ja. Stellen Sie den Filter in der RESTful-URI-Anforderung bereit.

Muss ich wirklich die gesamte Liste der Absender von Nachrichten senden, um sie jedes Mal zu blockieren, wenn ich die neue Nachrichtenliste anfordere?

Ja. Wie groß kann diese "Liste der zu blockierenden Nachrichtensender" sein? Eine kurze Liste von PKs?

Eine GET-Anfrage kann sehr groß sein. Bei Bedarf können Sie eine POST-Anfrage versuchen, obwohl dies wie eine Art Abfrage klingt.


28
"Nicht anmelden. Nicht abmelden. Anmeldeinformationen für die Anfrage angeben." Ich sehe Antworten wie diese immer in Fragen, wie man in einer REST-API zustandslos bleibt, ohne Details darüber, wo / wie man diese Anmeldeinformationen auf dem Client speichern soll. Sicherlich sollten wir Benutzername und Passwort nicht im lokalen Speicher speichern!
BeniRose

2
@BeniRose Können wir ein Token nicht in localstorage speichern und dieses Token in Anforderungen verwenden, die den Benutzer eindeutig identifizieren?
Nikhil Sahu

1
Nach meinem Verständnis hat Localstorage viele Sicherheitsbedenken. Aber es gibt auch eine Reihe anderer Probleme mit clientseitigen Sitzungen, wie das Ungültigmachen von Token, das Abmelden eines Benutzers usw.
BeniRose

3
Wenn Sie JWT mit einer Signatur verwenden, ist die Signaturüberprüfung schnell, sodass Sie die Gültigkeit dieses Status überprüfen können.
Archimedes Trajano

36

Sie haben vollkommen Recht, die Unterstützung vollständig zustandsloser Interaktionen mit dem Server stellt eine zusätzliche Belastung für den Client dar. Wenn Sie jedoch eine Anwendung skalieren möchten, ist die Rechenleistung der Clients direkt proportional zur Anzahl der Clients. Daher ist eine Skalierung auf eine hohe Anzahl von Clients viel praktikabler.

Sobald Sie dem Server ein wenig Verantwortung für die Verwaltung einiger Informationen im Zusammenhang mit den Interaktionen eines bestimmten Clients übertragen, kann diese Belastung schnell zunehmen und den Server verbrauchen.

Es ist ein Kompromiss.


32

Historische Ansicht der Benutzeranwendungsstatusverwaltung

Sitzungen im herkömmlichen Sinne behalten den Status des Benutzers in der Anwendung auf dem Server bei. Dies kann die aktuelle Seite in einem Flow sein oder was zuvor eingegeben wurde, aber noch nicht in der Hauptdatenbank gespeichert wurde.

Der Grund für diese Notwendigkeit war das Fehlen von Standards auf der Clientseite, um den Status effektiv aufrechtzuerhalten, ohne clientspezifische (dh browserspezifische) Anwendungen oder Plug-Ins zu erstellen.

HTML5- und XML-Header-Anforderungen haben im Laufe der Zeit den Gedanken standardisiert, komplexe Daten einschließlich des Anwendungsstatus auf der Client-Seite (dh dem Browser) auf standardmäßige Weise zu speichern, ohne zwischen den Servern hin und her zu wechseln.

Allgemeine Nutzung von REST-Services

REST-Services werden im Allgemeinen aufgerufen, wenn eine Transaktion ausgeführt werden muss oder wenn Daten abgerufen werden müssen.

REST-Services sollen von der clientseitigen Anwendung und nicht direkt vom Endbenutzer aufgerufen werden.

Authentifizierung

Für jede Anfrage an den Server sollte ein Teil der Anfrage das Autorisierungstoken enthalten. Die Implementierung ist anwendungsspezifisch, im Allgemeinen jedoch entweder a BASICoderCERTIFICATE Form der Authentifizierung.

Die formularbasierte Authentifizierung wird von REST-Services nicht verwendet. Wie oben erwähnt, sollen REST-Services jedoch nicht vom Benutzer, sondern von der Anwendung aufgerufen werden. Die Anwendung muss das Abrufen des Authentifizierungstokens verwalten. In meinem Fall habe ich Cookies mit JASPIC mit OAuth 2.0 verwendet, um eine Verbindung zu Google zur Authentifizierung herzustellen, und eine einfache HTTP-Authentifizierung für automatisierte Tests. Ich habe auch die HTTP-Header-Authentifizierung über JASPIC verwendet für lokale Tests verwendet (obwohl der gleiche Ansatz in SiteMinder ausgeführt werden kann).

Gemäß diesen Beispielen wird die Authentifizierung auf der Clientseite verwaltet (obwohl SiteMinder oder Google die Authentifizierungssitzung am Ende speichern würden). Gegen diesen Status kann nichts unternommen werden, sie ist jedoch nicht Teil der REST-Dienstanwendung.

Abrufanfragen

Abrufanforderungen in REST sind GETVorgänge, bei denen eine bestimmte Ressource angefordert wird und zwischengespeichert werden kann. Serversitzungen sind nicht erforderlich, da die Anforderung alles enthält, was zum Abrufen der Daten erforderlich ist: Authentifizierung und URI.

Transaktionsskripte

Wie oben erwähnt, ruft die clientseitige Anwendung selbst die REST-Services zusammen mit der Authentifizierung auf, die sie auch auf der Clientseite verwaltet.

Für REST-Services bedeutet dies, dass eine einzelne Anforderung an den REST-Server alles enthält, was für eine Einzelbenutzeroperation erforderlich ist, die alles tut, was in einer einzelnen Transaktion benötigt wird. Ein Transaktionsskript ist das Muster wird genannt.

Dies erfolgt POSTnormalerweise über eine Anfrage, es können jedoch auch andere PUTverwendet werden.

Viele erfundene Beispiele für REST (ich selbst habe dies getan) versuchten, so viel wie möglich von dem zu befolgen, was im HTTP-Protokoll definiert wurde. Nachdem ich das durchgegangen war, entschied ich mich, pragmatischer zu sein und überließ es nur GET und POST . Die POSTMethode muss nicht einmal das POST-REDIRECT-GET-Muster implementieren.

Unabhängig davon wird, wie oben erwähnt, die clientseitige Anwendung den Dienst aufrufen und die POSTAnforderung nur dann mit allen Daten aufrufen, wenn dies erforderlich ist (nicht jedes Mal). Dies verhindert ständige Anforderungen an den Server.

Umfragen

Obwohl REST auch zum Abrufen verwendet werden kann, empfehle ich es nur, wenn Sie es aus Gründen der Browserkompatibilität verwenden müssen. Dafür würde ich WebSockets verwenden, für die ich auch einen API-Vertrag entworfen hatte . Eine weitere Alternative für ältere Browser ist CometD.


27

REST ist sehr abstrakt. Es hilft, einige gute, einfache und reale Beispiele zu haben.

Nehmen Sie zum Beispiel alle wichtigen Social-Media-Apps - Tumblr, Instagram, Facebook und Twitter. Sie alle haben eine ewig scrollende Ansicht, in der je weiter Sie nach unten scrollen, desto mehr Inhalte sehen Sie immer weiter in der Zeit zurück. Wir alle haben jedoch den Moment erlebt, in dem Sie verlieren, wohin Sie gescrollt wurden, und die App Sie wieder nach oben zurücksetzt. Wenn Sie die App beenden und wieder öffnen, sind Sie wieder ganz oben.

Der Grund dafür ist, dass der Server Ihren Sitzungsstatus nicht gespeichert hat. Leider wurde Ihre Bildlaufposition nur im RAM des Clients gespeichert.

Glücklicherweise müssen Sie sich beim erneuten Herstellen der Verbindung nicht erneut anmelden. Dies liegt jedoch nur daran, dass Ihr clientseitig gespeichertes Anmeldezertifikat nicht abgelaufen ist. Löschen Sie die App und installieren Sie sie erneut. Sie müssen sich erneut anmelden, da der Server Ihre IP-Adresse nicht mit Ihrer Sitzung verknüpft hat.

Sie haben keine Anmeldesitzung auf dem Server, da diese REST einhalten.


Die obigen Beispiele beinhalten überhaupt keinen Webbrowser, aber im Back-End kommunizieren die Apps über HTTPS mit ihren Host-Servern. Mein Punkt ist, dass REST keine Cookies und Browser usw. beinhalten muss. Es gibt verschiedene Möglichkeiten, den clientseitigen Sitzungsstatus zu speichern.

Aber lassen Sie uns für eine Sekunde über Webbrowser sprechen, denn das bringt einen weiteren großen Vorteil von REST mit sich, über den hier niemand spricht.

Wenn der Server versucht hat, den Sitzungsstatus zu speichern, wie soll er dann jeden einzelnen Client identifizieren?

Ihre IP-Adresse konnte nicht verwendet werden, da viele Benutzer möglicherweise dieselbe Adresse auf einem gemeinsam genutzten Router verwenden. Wie also?

Die MAC-Adresse kann aus vielen Gründen nicht verwendet werden, nicht zuletzt, weil Sie in mehreren verschiedenen Facebook-Konten gleichzeitig in verschiedenen Browsern und in der App angemeldet sein können. Ein Browser kann leicht so tun, als wäre er ein anderer, und MAC-Adressen lassen sich genauso leicht fälschen.

Wenn der Server einen clientseitigen Status speichern muss, um Sie zu identifizieren, muss er ihn länger im RAM speichern als nur die Zeit, die für die Verarbeitung Ihrer Anforderungen benötigt wird, oder er muss diese Daten zwischenspeichern. Server haben eine begrenzte Menge an RAM und Cache, ganz zu schweigen von der Prozessorgeschwindigkeit. Der serverseitige Status addiert sich exponentiell zu allen drei. Wenn der Server einen Status über Ihre Sitzungen speichern soll, muss er diesen für jeden Browser und jede App, mit der Sie derzeit angemeldet sind, sowie für jedes andere Gerät, das Sie verwenden, separat speichern.


Also ... ich hoffe, Sie sehen jetzt, warum REST für die Skalierbarkeit so wichtig ist. Ich hoffe, Sie können sehen, warum der serverseitige Sitzungsstatus für die Skalierbarkeit des Servers und die angeschweißten Ambosse für die Fahrzeugbeschleunigung von Bedeutung sind.


Die Leute sind verwirrt, wenn sie denken, dass "Zustand" sich auf Informationen bezieht, die in einer Datenbank gespeichert sind. Nein, es bezieht sich auf alle Informationen, die sich im RAM des Servers befinden müssen, wenn Sie ihn verwenden.


13

Ich sehe, dass das Grundproblem hier darin besteht, die Sitzung mit dem Staat zu verwechseln . Und während REST gibt an, dass Sie sollten nicht mehr nur der Staat auf dem Server, nichts hindert Sie daran , Speichern einer Benutzersitzung .

Verwaltung des Staates auf dem Server bedeutet, dass Ihr Server genau weiß, was der Client tut (welche Seite er in welchem ​​Abschnitt der Anwendung anzeigt). Und das sollten Sie nicht tun müssen.

Ich stimme den anderen Leuten zu, die sagen, dass Sie den Sitzungsspeicher auf eine Mindestgröße beschränken sollten. und obwohl das gesunder Menschenverstand ist, hängt es tatsächlich auch von der Anwendung ab. Kurz gesagt, Sie können weiterhin eine Sitzung mit zwischengespeicherten Daten führen, um die Anforderungen mit geringerer Belastung des Servers zu verarbeiten, und die Authentifizierung verwalten, indem Sie dem Client ein temporäres Authentifizierungs- / Zugriffstoken zur Verwendung bereitstellen. Wenn die Sitzung / das Token abgelaufen ist, generieren Sie eine neue und bitten Sie den Client, sie zu verwenden.

Jemand könnte argumentieren, dass der Client das Token besser generieren sollte. Ich sage, es funktioniert in beide Richtungen, und es hängt von der Anwendung ab und davon, wer mit der API arbeiten wird.

Auch das Speichern einiger vertraulicher Sitzungsdaten auf dem Server sollte der richtige Weg sein. Sie können dem Kunden nicht vertrauen, dass er seinen Warenkorb behält, der (zum Beispiel) ein Feld mit dem Namen "isFreeGift" enthält. Solche Informationen sollten auf dem Server gespeichert werden.

Der von Santanu Dey in seiner Antwort bereitgestellte Videolink ist hilfreich. Schau es dir an, wenn du es nicht hast.

Nur eine Randnotiz: Es scheint, dass alle bereits gegebenen Antworten die Tatsache außer Acht lassen, dass einige Vorgänge den Server stark belasten könnten. Dies ist in Bezug auf Stromverbrauch, Hardwareverbrauch und Kosten relevant (für Server, die nach CPU-Zyklus gemietet werden). Ein guter Entwickler sollte bei der Optimierung seiner Anwendung nicht faul sein, auch wenn der Vorgang auf einer modernen CPU auf einem gemieteten Server, für den er die Strom- und Wartungskosten nicht bezahlt, sehr schnell ausgeführt werden kann.

Obwohl die Frage einige Jahre alt ist, hoffe ich, dass meine Antwort immer noch hilfreich ist.


4
Ich stimme diesem Gefühl im Allgemeinen zu, aber es gibt in jüngster Zeit den Trend zu behaupten, dass nicht einmal eine Sitzungskennung auf dem Server gespeichert werden sollte. Ich habe noch nicht herausgefunden, was die alternative Lösung ist. JWT wird gut angepriesen, kommt aber mit einer Handvoll Fallstricken: cryto.net/~joepie91/blog/2016/06/19/…
BeniRose

11

Statuslos bedeutet, dass der Status des Dienstes zwischen nachfolgenden Anforderungen und Antworten nicht bestehen bleibt. Jede Anfrage trägt ihre eigenen Benutzeranmeldeinformationen und wird einzeln authentifiziert. In Stateful ist jedoch jede Anfrage aus jeder vorherigen Anfrage bekannt. Alle statusbehafteten Anforderungen sind sitzungsorientiert, dh jede Anforderung muss Änderungen kennen und beibehalten, die in früheren Anforderungen vorgenommen wurden.

Die Bankanwendung ist ein Beispiel für eine zustandsbehaftete Anwendung. Wo sich der Benutzer zuerst anmeldet, dann eine Transaktion durchführt und sich abmeldet. Wenn der Benutzer nach dem Abmelden versucht, die Transaktion durchzuführen, kann er dies nicht tun.

Ja, das http-Protokoll ist im Wesentlichen ein zustandsloses Protokoll, aber um es aussagekräftig zu machen, verwenden wir HTTP-Cookies. Also ist SOAP standardmäßig. Aber es kann auch zustandsbehaftet gemacht werden, abhängig von dem Framework, das Sie verwenden.

HTTP ist zustandslos, aber wir können die Sitzung in unserer Java-Anwendung mithilfe eines anderen Sitzungsverfolgungsmechanismus beibehalten.

Ja, wir können die Sitzung auch im Webservice verwalten, unabhängig davon, ob es sich um REST oder SOAP handelt. Es kann mithilfe einer Bibliothek eines Drittanbieters implementiert werden oder Sie können es selbst implementieren.

Entnommen aus http://gopaldas.org/webservices/soap/webservice-is-stateful-or-stateless-rest-soap


11

Da ist kein Löffel.

Denken Sie nicht an Staatenlosigkeit wie "Senden Sie all Ihre Sachen immer wieder an den Server". Auf keinen Fall. Es wird immer einen Status geben - die Datenbank selbst ist schließlich eine Art Status, Sie sind ein registrierter Benutzer, sodass alle clientseitigen Informationen ohne die Serverseite nicht gültig sind. Technisch gesehen bist du nie wirklich staatenlos.

Jedes Mal ein Wort beim Login Debatte

Was bedeutet es überhaupt, nicht jedes Mal eine Sitzung zu führen und sich anzumelden? Einige bedeuten "jedes Mal das Passwort senden", das ist einfach nur dumm. Einige sagen "nah natürlich nicht, sende stattdessen ein Token " - siehe da, die PHP-Sitzung macht fast genau das. Es sendet eine Sitzungs-ID, die eine Art Token ist und hilft Ihnen dabei, Ihre persönlichen Daten zu erreichen, ohne jedes Mal u / pw erneut senden zu müssen. Es ist auch ziemlich zuverlässig und gut getestet. Und ja, praktisch, was sich in einen Nachteil verwandeln kann, siehe nächster Absatz.

Platzbedarf reduzieren

Was Sie stattdessen tun sollten und was wirklich Sinn macht, ist, Ihren Webserver-Footprint auf ein Minimum zu reduzieren. Sprachen wie PHP machen es sehr einfach, alles in den Sitzungsspeicher zu packen - aber Sitzungen haben einen Preis. Wenn Sie mehrere Webserver haben, müssen diese Sitzungsinformationen gemeinsam nutzen, da sie auch die Last gemeinsam nutzen. Jeder von ihnen muss möglicherweise die nächste Anforderung bearbeiten.

Ein gemeinsam genutzter Speicher ist ein Muss. Der Server muss mindestens wissen, ob jemand angemeldet ist oder nicht. (Und wenn Sie die Datenbank jedes Mal belästigen, wenn Sie dies entscheiden müssen, sind Sie praktisch zum Scheitern verurteilt.) Freigegebene Speicher müssen viel schneller als die Datenbank sein. Das bringt die Versuchung mit sich: Okay, ich habe einen sehr schnellen Speicher, warum nicht alles dort machen? - und dort laufen die Dinge auf die andere Weise böse.

Sie sagen also, Sitzungsspeicher auf ein Minimum beschränken?

Wieder ist es deine Entscheidung. Sie können dort aus Leistungsgründen Daten speichern (die Datenbank ist fast immer langsamer als Redis), Sie können Informationen redundant speichern, Ihr eigenes Caching implementieren, was auch immer - denken Sie daran, dass Webserver eine größere Last haben, wenn Sie viel Müll speichern auf sie. Wenn sie unter schwerer Last brechen (und dies auch tun), verlieren Sie wertvolle Informationen. Bei der REST-Denkweise ist alles, was in diesem Fall passiert, dass der Client dieselbe (!) Anfrage erneut sendet und diesmal bedient wird.

Wie macht man das dann richtig?

Hier gibt es keine Komplettlösung. Ich würde sagen, wählen Sie ein Maß an Staatenlosigkeit und gehen Sie damit um. Sitzungen mögen von einigen geliebt und von anderen gehasst werden, aber sie gehen nirgendwo hin. Senden Sie bei jeder Anfrage so viele Informationen, wie sinnvoll sind, vielleicht ein bisschen mehr. Aber interpretieren Sie Staatenlosigkeit nicht so, dass Sie keine Sitzung haben oder sich jedes Mal anmelden. Irgendwie muss der Server wissen, dass Sie es sind . PHP-Sitzungs-IDs sind eine gute Möglichkeit, manuell generierte Token eine andere.

Denken Sie und entscheiden Sie, lassen Sie Designtrends nicht für Sie denken.


1
"Denken Sie und entscheiden Sie, lassen Sie Designtrends nicht für Sie denken." Leider ist es heutzutage sehr üblich, Trends nur dumm zu folgen. Manchmal, wenn Sie SO lesen, erhalten Sie nur aufgrund des Trends dieselben Antworten.
100k

Ja, ich habe dies bei vielen Themen gesehen und wenn ich merke, was passiert, höre ich manchmal auf zu streiten. Damals waren alle verrückt danach, wie Content-Box besser ist als Border-Box. Es war eine Möglichkeit, Hass gegen den Internet Explorer zu zeigen. Dann kam der Bootstrap und plötzlich war jeder ein Border-Box-Gläubiger. Trends kommen, aber dann gehen sie. Verwenden Sie goto, verwenden Sie Tabellen, verwenden Sie iframes, wissen Sie einfach, was Sie tun und warum. Trendisten werden versuchen, Sie zu Fall zu bringen, dann registrieren sie sich und zahlen auf Ihrer Website. Welt wieder gerettet.
dkellner

@dkellner Ich habe diesen Teil nicht verstanden: "Der Server muss zumindest wissen, ob jemand angemeldet ist oder nicht. (Und wenn Sie die Datenbank jedes Mal belästigen, wenn Sie dies entscheiden müssen, sind Sie praktisch zum Scheitern verurteilt.)". Angenommen, Sie speichern Sitzungsdaten mit PHP in der Datenbank. Warum ist das Abfragen der Datenbank nach der Anmeldung schlecht (zum Scheitern verurteilt ist ein starkes Wort), da es ohnehin viele nachfolgende DB-Anfragen gibt, um die vollständigen Benutzerdaten und andere Dinge basierend auf der PHP-Sitzungs-ID abzurufen? Mit anderen Worten, DB-Abfragen sind in jedem Fall unvermeidlich. Wenn Sie keine PHP-Sitzungs-ID erhalten, wissen Sie, dass der Benutzer nicht authentifiziert ist und keine Abfrage erforderlich ist.
user2923322

Wenn Sie Tausende oder sogar Millionen von Benutzern haben, können Sie sich nicht den Luxus leisten, jedes Mal eine Verbindung zu db herzustellen, wenn Sie ein Keepalive, eine Standortaktualisierung, eine Nachrichtenumfrage oder etwas anderes durchführen möchten, das einen kurzen Check-in erfordert. Sie müssen diese Aufrufe ohne (oder mit minimalem) Datenbankzugriff implementieren. Deshalb kann es tödlich sein, wenn Sie Ihr gesamtes Konzept auf db aufbauen. Auch hier kann es Fälle geben, in denen eine gut gestaltete Datenbanklösung funktioniert, aber der typische Programmierer löst alles, indem er sagt: "Okay, zuerst stellen wir eine Verbindung her und rufen einige Benutzerinformationen ab." Baaaad Praxis.
dkellner


3

Der Hauptunterschied zwischen zustandslos und zustandsbehaftet besteht darin, dass die Daten jedes Mal an den Server zurückgegeben werden. Im Falle eines Statuslosen muss der Client alle Informationen bereitstellen, sodass möglicherweise bei jeder Anforderung viele Parameter übergeben werden müssen. In Stateful übergibt der Cliet diese Parameter einmal und sie werden vom Server verwaltet, bis sie vom Client erneut geändert werden.

IMO, API sollte zustandslos sein, was eine schnelle Skalierung ermöglicht.


2

Sie müssen die Client-Sitzung auf der Client-Seite verwalten. Dies bedeutet, dass Sie bei jeder Anforderung Authentifizierungsdaten senden müssen und wahrscheinlich, aber nicht unbedingt, einen speicherinternen Cache auf dem Server haben müssen, der Authentifizierungsdaten mit Benutzerinformationen wie Identität, Berechtigungen usw. koppelt.

Diese Einschränkung der REST- Staatenlosigkeit ist sehr wichtig. Ohne diese Einschränkung lässt sich Ihre serverseitige Anwendung nicht gut skalieren , da die Wartung jeder einzelnen Client-Sitzung die Achillesferse ist .


Wenn Sie bei jeder Anforderung Authentifizierungsdaten senden, wo / wie speichern Sie die Anmeldeinformationen auf dem Client, damit der Benutzer sie nicht bei jeder Anforderung erneut eingeben muss?
Amber

1

Wenn Sie einen RESTful-Service entwickeln, muss Ihr Benutzer authentifiziert sein, um angemeldet zu sein. Eine mögliche Option wäre, den Benutzernamen und das Kennwort jedes Mal zu senden, wenn Sie eine Benutzeraktion ausführen möchten. In diesem Fall speichert der Server überhaupt keine Sitzungsdaten.

Eine andere Möglichkeit besteht darin, eine Sitzungs-ID auf dem Server zu generieren und an den Client zu senden, damit der Client die Sitzungs-ID an den Server senden und sich damit authentifizieren kann. Dies ist viel sicherer als das Senden von Benutzername und Passwort jedes Mal, da jemand, der diese Daten in die Hand nimmt, sich als Benutzer ausgeben kann, bis der Benutzername und das Passwort geändert werden. Sie können sagen, dass sogar die Sitzungs-ID gestohlen werden kann und der Benutzer in diesem Fall imitiert wird und Sie Recht haben. In diesem Fall ist es jedoch nur möglich, sich als Benutzer auszugeben, solange die Sitzungs-ID gültig ist.

Wenn die RESTful-API Benutzername und Kennwort erwartet, um Benutzername und Kennwort zu ändern, kann der Hacker den tatsächlichen Benutzer nicht sperren, selbst wenn sich jemand als Benutzer mit der Sitzungs-ID ausgibt.

Eine Sitzungs-ID kann durch Einweg-Sperren (Verschlüsselung) von etwas generiert werden, das den Benutzer identifiziert und die Zeit zur Sitzungs-ID hinzufügt. Auf diese Weise kann die Ablaufzeit der Sitzung definiert werden.

Der Server kann Sitzungs-IDs speichern oder nicht. Wenn der Server die Sitzungs-ID speichert, verstößt er natürlich gegen die in der Frage definierten Kriterien. Es ist jedoch nur wichtig sicherzustellen, dass die Sitzungs-ID für den angegebenen Benutzer überprüft werden kann, sodass die Sitzungs-ID nicht gespeichert werden muss. Stellen Sie sich eine Möglichkeit vor, wie Sie E-Mails, Benutzer-IDs und einige benutzerspezifische private Daten wie die Lieblingsfarbe in eine Richtung verschlüsseln können. Dies wäre die erste Ebene, und Sie würden das Datum des Benutzernamens irgendwie zur verschlüsselten Zeichenfolge hinzufügen und eine Zwei- Weg Verschlüsselung. Wenn eine Sitzungs-ID empfangen wird, kann die zweite Ebene entschlüsselt werden, um zu bestimmen, welcher Benutzername der Benutzer behauptet und ob die Sitzungszeit richtig ist. Wenn dies gültig ist, Dann könnte die erste Verschlüsselungsstufe überprüft werden, indem diese Verschlüsselung erneut durchgeführt und überprüft wird, ob sie mit der Zeichenfolge übereinstimmt. Sie müssen keine Sitzungsdaten speichern, um dies zu erreichen.


Das macht Sinn
am

0

Das gesamte Konzept ist anders ... Sie müssen keine Sitzungen verwalten, wenn Sie versuchen, das RESTFul-Protokoll zu implementieren. In diesem Fall ist es besser, bei jeder Anfrage ein Authentifizierungsverfahren durchzuführen (während dies zusätzliche Kosten in Bezug auf die Leistung mit sich bringt - das Hashing-Passwort wäre ein gutes Beispiel. Keine große Sache ...). Wenn Sie Sitzungen verwenden - wie können Sie die Last auf mehrere Server verteilen? Ich wette, das RESTFul-Protokoll soll Sitzungen eliminieren - Sie brauchen sie nicht wirklich ... Deshalb wird es "zustandslos" genannt. Sitzungen sind nur erforderlich, wenn Sie nach einer Anforderung nichts anderes als Cookies auf einer Clientseite speichern können (am Beispiel eines alten, nicht Javascript / HTML5-unterstützenden Browsers). Im Falle eines RESTFul-Clients mit "vollem Funktionsumfang" ist die Aufbewahrung normalerweise sicherbase64(login:password) auf einer Clientseite (im Speicher), bis die Anwendung noch geladen ist - die Anwendung wird verwendet, um auf den einzigen Host zuzugreifen, und das Cookie kann nicht durch Skripte von Drittanbietern kompromittiert werden ...

Ich würde dringend empfehlen, die Cookie-Authentifizierung für RESTFul-Dienste zu deaktivieren. Schauen Sie sich Basic / Digest Auth an - das sollte für RESTFul-basierte Dienste ausreichen.


3
Was ist a client side (in memory) und wie ist es sicher, base64(login:password)auf Client-Seite zu speichern ?
RN Kushwaha

1
Nichts ist als "völlig sicher" definiert. Sie können jedoch in Betracht ziehen, OAuth2 zu verwenden, das eine bessere Sicherheit bietet als das Speichern der Base64-Zeichenfolge für API-Anforderungen (Basic Auth). Wenn Sie sich an Basic Auth halten, können Sie HTTPS für eine bessere Sicherheit verwenden.
felixwcf

3
RN Kushwaha, diese Frage scheint niemand beantworten zu wollen, wenn er Ihnen sagt, dass Sie die Speicherung der Sitzung auf dem Server beenden und im Client speichern sollen.
BeniRose

0

REST ist zustandslos und behält keine Zustände zwischen den Anforderungen bei. Client-Cookies / -Header werden so eingestellt, dass sie den Benutzerstatus wie die Authentifizierung beibehalten. Angenommen, der Benutzername / das Kennwort des Clients werden durch einen Authentifizierungsmechanismus des dritten Teils überprüft - OTP gerneation der zweiten Ebene usw. Sobald der Benutzer authentifiziert wurde, werden Header / Cookies zum Ruhezustand des Service-Endpunkts angezeigt, und wir können den Benutzer als Authentifizierung annehmen, da der Benutzer gültige Header / Cookies mitbringt . Jetzt werden bestimmte Informationen von Benutzern wie IP entweder im Cache gespeichert und danach, wenn eine Anforderung von derselben IP (Mac-Adresse) für aufgelistete Ressourcen kommt, ist der Benutzer zulässig. Der Cache wird für eine bestimmte Zeit beibehalten, die nach Ablauf der Zeit ungültig wird. So kann entweder der Cache verwendet werden oder DB-Einträge können verwendet werden, um Informationen s / w der Anforderungen beizubehalten.


0

Statuslos bedeutet hier, dass Status- oder Metadaten der Anforderung auf der Serverseite nicht verwaltet werden. Wenn jede Anforderung oder jeder Benutzerstatus auf dem Server beibehalten wird, führt dies zu Leistungsengpässen. Der Server wird nur mit den erforderlichen Attributen angefordert, um bestimmte Vorgänge auszuführen.

Um Sitzungen verwalten oder Benutzern eine benutzerdefinierte Erfahrung bieten zu können, müssen einige Metadaten oder der Status der Benutzerpräferenzen des Benutzers sowie der vergangene Anforderungsverlauf beibehalten werden. Dies kann durch Verwalten von Cookies, versteckten Attributen oder in Sitzungsobjekten erfolgen.

Dadurch kann der Benutzerstatus in der Anwendung beibehalten oder verfolgt werden.

Hoffe das hilft!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.