Können Sie mir helfen, das zu verstehen? "Häufige REST-Fehler: Sitzungen sind irrelevant"

159

Haftungsausschluss: Ich bin neu in der REST-Denkschule und versuche, mich darum zu kümmern.

Ich lese diese Seite, Häufige REST-Fehler , und habe festgestellt, dass mich der Abschnitt über irrelevante Sitzungen völlig verblüfft. Dies ist, was die Seite sagt:

Es sollte nicht erforderlich sein, dass sich ein Client "anmeldet" oder "eine Verbindung herstellt". Die HTTP-Authentifizierung erfolgt automatisch für jede Nachricht. Clientanwendungen sind Konsumenten von Ressourcen, nicht von Diensten. Daher gibt es nichts, bei dem man sich anmelden kann! Angenommen, Sie buchen einen Flug über einen REST-Webservice. Sie erstellen keine neue "Sitzungs" -Verbindung zum Dienst. Stattdessen bitten Sie das "Objekt zum Erstellen der Reiseroute", eine neue Reiseroute zu erstellen. Sie können mit dem Ausfüllen der Lücken beginnen, aber dann an einer anderen Stelle im Web eine völlig andere Komponente erhalten, um einige andere Lücken auszufüllen. Es gibt keine Sitzung, daher gibt es kein Problem beim Migrieren des Sitzungsstatus zwischen Clients. Es gibt auch kein Problem der "Sitzungsaffinität"

Okay, ich verstehe, dass die HTTP-Authentifizierung bei jeder Nachricht automatisch erfolgt - aber wie? Wird der Benutzername / das Passwort bei jeder Anfrage gesendet? Erhöht das nicht nur die Angriffsfläche? Ich habe das Gefühl, dass mir ein Teil des Puzzles fehlt.

Wäre es beispielsweise schlecht, einen REST-Service zu haben /session, der eine GET-Anforderung akzeptiert, bei der Sie als Teil der Anforderung einen Benutzernamen / ein Kennwort übergeben und bei erfolgreicher Authentifizierung ein Sitzungstoken zurückgeben, könnte dies der Fall sein zusammen mit nachfolgenden Anfragen weitergegeben? Ist das aus REST-Sicht sinnvoll oder fehlt das?

rauben
quelle
Jede Anfrage wird immer authentifiziert, Sitzungsentführung ist eine Sache. Ruhe macht dies offensichtlicher, aber nicht exponierter.
Jasen

Antworten:

79

Um RESTful zu sein, sollte jede HTTP-Anforderung genügend Informationen für sich enthalten, damit der Empfänger sie so verarbeiten kann, dass sie vollständig mit der zustandslosen Natur von HTTP übereinstimmt.

Okay, ich verstehe, dass die HTTP-Authentifizierung bei jeder Nachricht automatisch erfolgt - aber wie?

Ja, der Benutzername und das Passwort werden bei jeder Anfrage gesendet. Die gängigen Methoden hierfür sind die grundlegende Zugriffsauthentifizierung und die Digest-Zugriffsauthentifizierung . Und ja, ein Lauscher kann die Anmeldeinformationen des Benutzers erfassen. Man würde also alle gesendeten und empfangenen Daten mit Transport Layer Security (TLS) verschlüsseln .

Wäre es schlecht, einen REST-Service zu haben, z. B. / session, der eine GET-Anforderung akzeptiert, bei der Sie einen Benutzernamen / ein Kennwort als Teil der Anforderung übergeben und ein Sitzungstoken zurückgeben, wenn die Authentifizierung erfolgreich war dann mit nachfolgenden Anfragen weitergegeben werden? Ist das aus REST-Sicht sinnvoll oder fehlt das?

Dies wäre nicht RESTful, da es den Status trägt, aber es ist ziemlich häufig, da es für Benutzer eine Annehmlichkeit ist. Ein Benutzer muss sich nicht jedes Mal anmelden.

Was Sie in einem "Sitzungstoken" beschreiben, wird üblicherweise als Anmeldecookie bezeichnet . Wenn Sie beispielsweise versuchen, sich bei Ihrem Yahoo! Konto gibt es ein Kontrollkästchen mit der Aufschrift "Halten Sie mich 2 Wochen lang angemeldet". Dies bedeutet im Wesentlichen (in Ihren Worten): "Halten Sie mein Sitzungstoken 2 Wochen lang am Leben, wenn ich mich erfolgreich anmelde." Webbrowser senden solche Anmelde-Cookies (und möglicherweise andere) mit jeder HTTP-Anfrage, die Sie für Sie anfordern.

z8000
quelle
5
Diese Antwort macht für mich keinen Sinn. Zunächst heißt es, dass es in Ordnung ist, das Login und das Passwort jedes Mal und damit auch einmal zu übergeben, was Sinn macht. Anschließend wird die Idee vorgeschlagen, den erfolgreichen Anmeldestatus in Form eines Tokens an den Client zurückzugeben. Bei Bedarf kann das Token den Erstellungszeitpunkt codieren. Wir dürfen auf jeden Fall Informationen an den Kunden zurücksenden. Dieser Vorschlag scheint mir in Ordnung zu sein. Die Antwort besagt, dass es nicht in Ordnung ist, weil "es den Status trägt", aber ist die Idee von "ST" in "REST" nicht, dass der Status zwischen dem Client und dem Server übertragen werden kann?
33

Es ist nicht ungewöhnlich, dass ein REST-Service für jede HTTP-Anforderung eine Authentifizierung erfordert. Beispielsweise erfordert Amazon S3, dass jede Anforderung eine Signatur hat, die aus den Benutzeranmeldeinformationen, der genauen auszuführenden Anforderung und der aktuellen Uhrzeit abgeleitet wird. Diese Signatur ist auf der Clientseite einfach zu berechnen, kann vom Server schnell überprüft werden und ist für einen Angreifer, der sie abfängt, nur von begrenztem Nutzen (da sie auf der aktuellen Zeit basiert).

Greg Hewgill
quelle
3
+1 können Sie bitte näher darauf eingehen: Ist dies für einen Angreifer, der es abfängt, von begrenztem Nutzen (da es auf der aktuellen Zeit basiert) ? Sprechen Sie nicht über ein Cookie, das einen verschlüsselten Benutzernamen und ein Passwort enthält? wie SO? (IMHO)
Royi Namir
2
@ RoyiNamir: Ich spreche nicht von einem Cookie. Die von S3 verwendete Signatur ist ein Parameter für die HTTP-Anforderung, jedoch kein Cookie. Sie wird für jede Anforderung neu berechnet.
Greg Hewgill
Wenn ich also Informationen über einen Benutzer speichern muss, wo würde ich sie speichern? in db? Ich möchte nicht jede Anfrage an db senden ... und trotzdem möchte ich rest verwenden ... können Sie bitte helfen?
Royi Namir
@ RoyiNamir: Wenn Sie spezielle Fragen zum Erreichen eines Ziels haben, stellen Sie bitte eine neue Frage . Ich kann hier in den Kommentaren keine weiteren Fragen beantworten.
Greg Hewgill
Es klingt für mich wie eine Anwendung der Digest-Zugriffsauthentifizierung en.wikipedia.org/wiki/Digest_access_authentication .
Wangkaibule
10

Viele Leute verstehen REST-Principales nicht sehr klar. Die Verwendung eines Sitzungstokens bedeutet nicht, dass Sie immer einen Status haben. Der Grund für das Senden eines Benutzernamens / Kennworts bei jeder Anforderung ist nur die Authentifizierung und derselbe für das Senden eines Tokens (generiert durch Anmeldung) Nur um zu entscheiden, ob der Client die Berechtigung hat, Daten anzufordern oder nicht, verletzen Sie REST-Konvetionen nur, wenn Sie entweder den Benutzernamen / das Passwort oder die Sitzungstoken verwenden, um zu entscheiden, welche Daten angezeigt werden sollen! Stattdessen müssen Sie sie nur zur Authentifizierung verwenden (um Daten anzuzeigen oder um Daten nicht anzuzeigen).

In Ihrem Fall sage ich JA, dies ist RESTy, aber vermeiden Sie die Verwendung nativer PHP-Sitzungen in Ihrer REST-API und generieren Sie Ihre eigenen Hash-Token, die in einem bestimmten Zeitraum ablaufen!

EvilThinker
quelle
1
Vielen Dank. Warum sollte man native PHP-Sitzungen vermeiden und stattdessen eigene Hash-Token verwenden?
Matthew
Kein brillanter Grund, sage ich, nur für mehr Sicherheit und mehr Kontrolle.
EvilThinker
Dies ist besser als die akzeptierte Antwort. Zumindest akzeptiert es den Vorschlag als RESTy, was Sinn macht. Ich verstehe jedoch nicht, warum die übergebenen Informationen nicht für eine benutzerabhängige Autorisierung verwendet werden können. Einige Benutzer haben möglicherweise Zugriff auf einige Daten, andere nicht. Das macht das Protokoll nicht unruhig.
8

Nein, es geht nicht daneben. Googles ClientLogin funktioniert genau so, mit der bemerkenswerten Ausnahme, dass der Client angewiesen wird, mithilfe einer HTTP 401-Antwort zur "/ session" zu wechseln . Dies schafft jedoch keine Sitzung, sondern nur eine Möglichkeit für Clients, sich (vorübergehend) zu authentifizieren, ohne die Anmeldeinformationen im Klartext zu übergeben, und für den Server, die Gültigkeit dieser temporären Anmeldeinformationen nach eigenem Ermessen zu kontrollieren.

Mogsie
quelle
11
@ unforgiven3 Solange das zurückgegebene Token nur zur Authentifizierung des Benutzers verwendet wird und nicht vom Server verwendet wird, um den Benutzer einem anderen auf dem Server gespeicherten Status zuzuordnen, werden keine REST-Einschränkungen verletzt.
Darrel Miller
4
@ unforgiven3 Das vom Server zurückgegebene Token ist praktisch ein Beweis dafür, dass der Benutzer der ist, für den er sich ausgibt. Anstelle jeder Anforderung, die Benutzername und Kennwort enthält, enthält jede Anforderung das Token, das so aufgebaut ist, dass der Server von seiner Richtigkeit überzeugt sein kann.
Darrel Miller
1
@ unforgiven3, Darrel hat recht. Das zurückgesendete Token müsste vom Client bei jeder HTTP-Anforderung gesendet werden, genau wie bei der einfachen Digest-Authentifizierung, bis das Token abläuft. In diesem Fall kann der Client die Anmeldung wiederholen und den Benutzer optional nach Anmeldeinformationen oder was auch immer fragen. Ich könnte die Antwort ausarbeiten, wenn Sie wollen. edit: (Und danke, dass
du
1
Kein Problem, Mogsie, immer interessant, diese Art von Dingen zu diskutieren :-) Ich glaube, ich sehe, wohin ihr damit geht, leider verstehe ich einfach nicht genug über Digest-Authentifizierung, um das wirklich zu verstehen (meistens einfach nicht verstehen, wie das Token bei jeder HTTP-Anforderung zurückgesendet wird, aber das scheint ein Implementierungsdetail zu sein). Jetzt verstehe ich jedoch, warum diese Methode nicht gegen REST-Prinzipien verstößt. Danke für die Antworten!
Rob
6
@ unforgiven3, Dies kann helfen: Das Token ist eine signierte Information. Es ist also in sich geschlossen. Der Server kann das Token validieren, ohne einen zuvor gespeicherten Status zu überprüfen. Es ist also nur ein Zustand, der auf dem Client gespeichert und hin und her übertragen wird.
Iravanchi
5

Okay, ich verstehe, dass die HTTP-Authentifizierung bei jeder Nachricht automatisch erfolgt - aber wie?

"Autorisierung:" HTTP-Header vom Client gesendet. Entweder einfach (einfacher Text) oder verdauen.

Wäre es schlecht, einen REST-Service zu haben, z. B. / session, der eine GET-Anforderung akzeptiert, bei der Sie einen Benutzernamen / ein Kennwort als Teil der Anforderung übergeben und ein Sitzungstoken zurückgeben, wenn die Authentifizierung erfolgreich war dann mit nachfolgenden Anfragen weitergegeben werden? Ist das aus REST-Sicht sinnvoll oder fehlt das?

Die gesamte Idee einer Sitzung besteht darin, statusbehaftete Anwendungen mithilfe des zustandslosen Protokolls (HTTP) und des dummen Clients (Webbrowser) zu erstellen, indem der Status auf der Serverseite beibehalten wird. Eines der REST-Prinzipien lautet: "Jede Ressource kann mithilfe einer universellen Syntax zur Verwendung in Hypermedia-Links eindeutig adressiert werden . " Auf Sitzungsvariablen kann nicht über URI zugegriffen werden. Eine wirklich RESTful-Anwendung würde den Status auf der Clientseite beibehalten und alle erforderlichen Variablen per HTTP senden, vorzugsweise in der URI.

Beispiel: Suche mit Paginierung. Sie hätten eine URL im Formular

http://server/search/urlencoded-search-terms/page_num

Es hat viel mit Lesezeichen-URLs gemeinsam

vartec
quelle
4
Auf Authentifizierungsinformationen kann jedoch auch nicht über URI zugegriffen werden. Alle sprechen davon, Authentifizierungsinformationen als Teil des Anforderungsheaders zu senden. Wie unterscheidet sich das vom Einfügen eines Sitzungstokens in die Anforderung? Ich sage nicht, dass Sie das Sitzungstoken in der URI verwenden, sondern in Daten, die in der Anforderung übergeben wurden.
Rob
Die Authentifizierung stellt fest, ob Sie zur Ausführung dieser Aktion berechtigt sind und in der RESTful-Anwendung das Ergebnis nicht beeinflussen.
Vartec
4
Ein Sitzungstoken legt auch fest, ob Sie zur Ausführung dieser Aktion berechtigt sind. Was meinst du damit, dass es das Ergebnis nicht beeinflussen würde? Wenn der Anrufer nicht autorisiert ist, wird der Fehler Nicht autorisiert angezeigt. Gleiches gilt für ein Sitzungstoken. Ich sehe den Unterschied wirklich nicht?
Rob
3
Nein, das Sitzungstoken ist ein Handle für den Status, der auf dem Server gespeichert ist. Das ist einfach nicht RESTful. Was die nicht autorisierten betrifft, sehe ich das nicht als Ergebnis. Ich würde das lieber als Ausnahme betrachten (wie bei try / catch).
Vartec
Fair genug, vartec - das macht Sinn. Vielen Dank für das Follow-up!
Rob
3

Ich denke, Ihr Vorschlag ist in Ordnung, wenn Sie die Lebensdauer der Client-Sitzung steuern möchten. Ich denke, dass die RESTful-Architektur Sie dazu ermutigt, zustandslose Anwendungen zu entwickeln. Wie @ 2pence schrieb, "sollte jede HTTP-Anfrage genug Informationen für sich enthalten, damit ihr Empfänger sie verarbeiten kann, um in völliger Übereinstimmung mit der zustandslosen Natur von HTTP zu sein" .

Dies ist jedoch nicht immer der Fall. Manchmal muss die Anwendung feststellen, wann sich der Client anmeldet oder abmeldet, und Ressourcen wie Sperren oder Lizenzen basierend auf diesen Informationen verwalten. Siehe meine Follow - up - Frage für ein Beispiel eines solchen Falles.

LiorH
quelle