Abmelden: GET oder POST?

433

Bei dieser Frage geht es nicht darum, wann GET oder POST im Allgemeinen verwendet werden soll. Es handelt sich um die empfohlene Methode zum Abmelden von einer Webanwendung. Ich habe viele Informationen über die Unterschiede zwischen GET und POST im allgemeinen Sinne gefunden, aber für dieses spezielle Szenario keine eindeutige Antwort gefunden.

Als Pragmatiker neige ich dazu, GET zu verwenden, da die Implementierung viel einfacher ist als POST. Lass einfach einen einfachen Link fallen und du bist fertig. Dies scheint bei der überwiegenden Mehrheit der Websites der Fall zu sein, an die ich denken kann, zumindest von oben. Sogar der Stapelüberlauf übernimmt das Abmelden mit GET.

Was mich zögern lässt, ist das (wenn auch alte) Argument, dass einige Webbeschleuniger / Proxys Seiten vorab zwischenspeichern, indem sie jeden auf der Seite gefundenen Link abrufen, sodass der Benutzer eine schnellere Antwort erhält, wenn er darauf klickt. Ich bin nicht sicher, ob dies noch zutrifft, aber wenn dies der Fall wäre, würde theoretisch ein Benutzer mit einem dieser Beschleuniger aus der Anwendung geworfen, sobald er sich anmeldet, da sein Beschleuniger die Abmeldung finden und abrufen würde Link, auch wenn sie nie darauf geklickt hat.

Alles, was ich bisher gelesen habe, schlägt vor, POST für "destruktive Aktionen" zu verwenden, während Aktionen, die den internen Status der Anwendung nicht ändern - wie Abfragen und dergleichen - mit GET behandelt werden sollten . Auf dieser Grundlage lautet die eigentliche Frage hier:

Wird das Abmelden von einer Anwendung als destruktive Aktion angesehen / ändert sich der interne Status der Anwendung?

Daniel Liuzzi
quelle
Angenommen, Sie besuchen die Website zum ersten Mal und der Link zum Abmelden ist nicht vorhanden. Sie werden beim Anmelden abgemeldet. Nachdem Sie sich ein zweites Mal angemeldet haben, ist dies in Ordnung, da die Abmelde-URL bereits zwischengespeichert ist. Man kann jedoch davon ausgehen, dass jeder anständige Beschleuniger die meisten Abmelde-URLs herausfiltern kann.
HyperCas
2
HyperCas, Beschleuniger, die Abmelde-URLs herausfiltern, war eine Theorie, über die ich nachdachte, und einer der Gründe, warum ich mich entschied, die Frage zu stellen. Ich zögere ein wenig, nur der Beschleunigerlogik zu vertrauen, und eines Tages beschwert sich eine Benutzerin mit einem beschissenen Beschleuniger, dass sie sich nicht anmelden kann. Wissen Sie, ob sie einem Standard folgen oder ob ein solcher Standard existiert?
Daniel Liuzzi
Jeder Accelerator, der automatisch ein Formular gesendet hat (zum Beispiel), wäre Malware IMO ... Es ist völlig unlogisch zu glauben, dass ein Accelerator ein Formular automatisch sendet. Stellen Sie sich vor, Sie besuchen Google. Wie könnte es das Suchformular einreichen? Niemand kann Malware erklären, da sie zu unvorhersehbar ist und nicht den Regeln entspricht.
Alex
3
@AlexW - Ich denke du hast meine Frage falsch verstanden. Das von mir vorgeschlagene Beschleunigerszenario besteht darin, ein mögliches Problem bei der Verwendung von GET und nicht von POST aufzuzeigen. Es gibt also kein Formular zum Posten, sondern nur einfache Links, denen Beschleuniger ohne Probleme folgen würden.
Daniel Liuzzi
1
Mir ist klar, dass ich dafür Jahre zu spät bin, aber Alex, das ist nicht das, worüber Daniel fragt. Er sagt, wenn ein Benutzer auf einen Abmeldelink klickt und ein Beschleuniger die zwischengespeicherte Abmeldeseite zurückgibt, ohne dass sie die Anwendung trifft, bleibt der Benutzer angemeldet. Dies hat nichts mit Malware zu tun, obwohl die Überprüfung einer User-Agent-Zeichenfolge nicht behoben werden kann sowieso nichts.
Rob Grant

Antworten:

474

Verwenden Sie POST.

Im Jahr 2010 war die Verwendung GETwahrscheinlich eine akzeptable Antwort. Aber heute (2013) werden Browser Seiten vorab abrufen, von denen sie glauben, dass Sie sie als nächstes besuchen werden.

Hier ist einer der StackOverflow-Entwickler, der auf Twitter über dieses Problem spricht:

Ich möchte meiner Bank dafür danken, dass sie eine GET-Anfrage abgemeldet hat, und dem Chrome-Team für das praktische Vorabrufen von URLs. - Nick Craver ( @Nick_Craver ) 29. Januar 2013

Unterhaltsame Tatsache: StackOverflow diente zum Abmelden über GET, aber nicht mehr.

David Murdoch
quelle
2
Danke für dieses Update, Dave. Ich habe nicht einmal bemerkt, dass SO ihre Abmeldung auf POST umgestellt hat, und ich hatte ehrlich gesagt keine Ahnung, dass Chrome mit integriertem Pre-Fetching ausgestattet ist. Schließlich hätte der von Ihnen zitierte Trottel niemals ein besseres Beispiel für das in meinem Artikel beschriebene Problem bieten können meine Frage und bestätigt meinen Verdacht. Ich stimme Ihrer Antwort zu und mache sie zur akzeptierten Antwort.
Daniel Liuzzi
4
In meinem Browser sieht die Abmeldung von Stackoverflow wie folgt aus: <a href="https://stackoverflow.com/users/logout"> Abmelden </a> </ li> </ em> Dies ist ein GET, kein POST
Bootscodierer
9
@ Mark0978, klicken Sie auf den Link.
David Murdoch
2
Interessant. Das ist wahrscheinlich eine meiner am wenigsten bevorzugten Funktionen, eine Abmeldung, bei der ich gefragt werde, ob ich mir sicher bin. Vermutlich verhindert dies, dass der Prefetch Sie abmeldet, aber Amazon, Ebay und Gmail verwenden alle GET zum Abmelden, ohne dass diese Trickseite zwischen dem, was dem Benutzer mitgeteilt wird, Abmelden und dem tatsächlichen Abmeldeereignis liegt. Ich würde mir vorstellen, dass zwischen den Seiten viele Leute fälschlicherweise glauben würden, dass sie abgemeldet sind. Die Probleme damit auf SO sind minimal, kein Geld beteiligt, und 99% von allem ist sowieso öffentlich.
Bootscodierer
7
@Red Nach dem HTTP / 1.1-Standard ist dies der Fehler des Servers, nicht der des Browsers. Es wird erwartet, dass GET keine Nebenwirkungen auf der Serverseite hat. Der Standard besagt sogar, dass "der Benutzer die Nebenwirkungen nicht angefordert hat und daher nicht für sie zur Rechenschaft gezogen werden kann".
Augen
45

In REST sollte es keine Sitzung geben, daher gibt es nichts zu zerstören. Ein REST-Client authentifiziert sich bei jeder Anforderung. Angemeldet oder abgemeldet ist nur eine Illusion.

Was Sie wirklich fragen, ist, ob der Browser die Authentifizierungsinformationen bei jeder Anfrage weiter sendet.

Wenn Ihre Anwendung die Illusion erzeugt, angemeldet zu sein, sollten Sie sich möglicherweise mit Javascript "abmelden" können. Keine Hin- und Rückfahrt erforderlich.


Fielding Dissertation - Abschnitt 5.1.3

Jede Anforderung von Client zu Server muss alle Informationen enthalten, die zum Verständnis der Anforderung erforderlich sind, und darf keinen auf dem Server gespeicherten Kontext nutzen. Der Sitzungsstatus wird daher vollständig auf dem Client gespeichert

Darrel Miller
quelle
1
Das war mir eigentlich nicht bewusst. Dann wird meine App wohl überhaupt nicht sehr RESTful sein, da ich ASP.NET MVC mit FormsAuthentication verwende und sie auf Sitzungen beruht ...
Daniel Liuzzi
18
In der Praxis werden die Anmeldeinformationen jedoch in einem Cookie httponlygespeichert, das mit dem Attribut gekennzeichnet ist, um einige xss-Risiken zu vermeiden. Dies bedeutet, dass sie nur vom Server zurückgesetzt werden können (ohne das Cookie manuell zu
löschen
6
'Manuell' wie im Benutzer geht zu den Browsereinstellungen und wählt die Option 'Cookies löschen'. Kaum eine akzeptable Möglichkeit, sich von einer Website abzumelden.
Remus Rusanu
1
@Remus Ahhh, wie der berühmte Webbrowser das Schreiben von Web-Apps so schmerzhaft macht.
Darrel Miller
1
@DarrelMiller Ja, jedoch ist das Nicht-Widerrufen eines JWT auf der Serverseite eine Sicherheitslücke. Selbst wenn die Token nicht auf dem Server gespeichert sind, sollten sie auf die schwarze Liste gesetzt werden, wenn sich ein Benutzer abmeldet / Kennwörter ändert / Rollen / Beenden / usw. ändert, um Missbrauch zu verhindern (zumindest bis sie ablaufen).
Java-Addict301
38

Eine Möglichkeit, GETdie hier missbraucht werden könnte, besteht darin, dass eine Person (Konkurrent vielleicht :) ein Bild-Tag mit src="<your logout link>"ÜBERALL im Internet platziert hat. Wenn ein Benutzer Ihrer Website auf diese Seite stößt, wird er unwissentlich abgemeldet.

Raveren
quelle
4
Nein, das ist nicht richtig. Ein Abmeldelink funktioniert nur, wenn die richtigen Cookie-Daten gesendet werden, die nicht von einer anderen Domain stammen. Und selbst wenn die Sitzungs-ID in der URL gespeichert ist, würde dies auch nicht funktionieren, da sich diese für jede Sitzung ändern.
Richard H
4
Wow, daran habe ich nie gedacht! Es gibt also einen weiteren Grund, GET nicht zu verwenden, und einen weiteren Grund, warum ich nicht verstehe, warum jeder das tut. Verdammt, jetzt bin ich versucht, auch ein stackoverflow.com/users/logout "Bild" in meinen Beitrag aufzunehmen und zu sehen, was passiert :-D
Daniel Liuzzi
24
src = ist eine einfache Browseranforderung, die nicht vom Server, sondern vom Client stammt. Es trägt alle Cookies und kommt von der Benutzer-IP. Aus diesem Grund funktionieren Anzeigenverfolgungspixel. Die einzige Möglichkeit, einen solchen Exploit zu ermitteln, besteht darin, den Referrer zu überprüfen.
Raveren
12
SuperLogout.com macht genau das ( /logoutURLs in versteckte Bilder laden ) und es funktioniert.
Dan Dascalescu
9
re: SuperLogout ... Ich weiß nicht, warum ich darauf geklickt habe.
MI Wright
21

Um richtig zu sein, sind GET / POST (oder andere Verben) Aktionen für eine Ressource (adressiert durch URL) - es geht also im Allgemeinen um den Status der Ressource und nicht um den Anwendungsstatus als solchen. In wahrer Stimmung sollten Sie also eine URL haben, z. B. [host name]\[user name]\session'LÖSCHEN' wäre das richtige Verb für die Abmeldeaktion.

Die Verwendung [host name]\bla bla\logoutals URL ist nicht wirklich ein REST-Vollweg (IMO). Warum also über die korrekte Verwendung von GET / POST debattieren?

Natürlich verwende ich GET auch für eine Abmelde-URL in meinen Anwendungen :-)

VinayC
quelle
2
In diesem Fall würde ich dann argumentieren, dass es unnötig erscheint, den Teil [Benutzername] in der URL zu haben, da sich Benutzer immer von ihrer eigenen Sitzung abmelden (dh LÖSCHEN) . nie andere Benutzer ':-)
Daniel Liuzzi
1
Nicht wirklich - wir sagen, dass Sitzung eine Ressource ist und wir sie löschen möchten. Um eine Sitzung einheitlich ansprechen zu können, muss der Benutzername als Teil der URL angegeben werden. Ihr Argument ist so gut wie zu sagen, dass das Ausgeben einer PUT-Aktion für [Fotogalerie] \ Bilder bedeutet, dass Sie Ihre Fotos hinzufügen (verfügbar unter [Fotogalerie] \ [Benutzername] \ Bilder). Unterschiedliche Ressourcen müssen explizit angesprochen werden, es kann keine implizite Aussage darüber geben. Auf der Website können andere Benutzer möglicherweise Bilder zu Ihrer Galerie hinzufügen. Dies ist Teil der Zugriffskontrolle, ebenso wie Sie einen Superuser haben können, der die Sitzungen anderer Personen beenden kann.
VinayC
1
Philosophisch gesehen könnte man Sitzungen und Fotos als "Ressourcen" bezeichnen, aber realistisch würde ich sie nicht gleich behandeln. Sitzungen sind immer an sich auf den aktuellen Benutzer beschränkt (daher der Name Sitzung), und zumindest in ASP.NET gibt es keine Möglichkeit, auf die Sitzungen eines anderen Benutzers zuzugreifen. Selbst der Anwendungsentwickler hat keine direkte Möglichkeit, alle aktiven Sitzungen aufzulisten oder Sitzungen einzeln abzubrechen. Sie könnten die Anwendung neu starten, um alle Sitzungen (InProc) zu beenden, aber ich würde diese Zugriffskontrolle nicht nennen. Abgesehen von den URLs bleibt die Frage weiterhin: GET oder POST?
Daniel Liuzzi
Ressource, daher ihre Adresse (URL), sind ein wichtiger Bestandteil von REST. Wenn Sie also wie gesagt URL auswählen, wird LÖSCHEN zum richtigen Wort - nicht GET oder POST. Selbst wenn Sie sich auf ASP.NET beschränken, können Sie jederzeit über einen benutzerdefinierten Statusanbieter verfügen, mit dem Sie Sitzungen auflisten und bei Bedarf andere Sitzungen beenden können. Für sofort einsatzbereite In-Proc-Sitzungen sollte Ihnen das Fummeln in global.asax die Funktionalität bieten. Es ist wirklich eine Frage, ob eine solche Funktionalität benötigt wird oder nicht. Für seltene Bedürfnisse neigen die Leute dazu, die Website neu zu starten, um die Leute von der Website zu werfen.
VinayC
Das macht für mich am meisten Sinn. Geben Sie der Web-API eine Sitzungsroute und rufen Sie DELETE auf. Sei das ../session oder ../session/current. Thankx @VinayC
Simon Hooper
16

Das Abmelden hat nichts mit der Anwendung selbst zu tun. Es ändert den Status des Benutzers in Bezug auf die Anwendung. In diesem Fall basiert Ihre Frage anscheinend eher darauf, wie der Befehl vom Benutzer initiiert werden soll, um diese Aktion zu starten. Da dies keine "destruktive Aktion" ist und sicher ist, dass die Sitzung abgebrochen oder zerstört wird, aber weder Ihre Anwendung noch Ihre Daten geändert werden, ist es nicht unmöglich, beiden Methoden zu erlauben, einen Abmeldevorgang einzuleiten. Der Beitrag sollte von allen vom Benutzer initiierten Aktionen verwendet werden (z. B. - Benutzer klickt auf "Abmelden"), während get für von der Anwendung initiierte Abmeldungen reserviert werden kann (z. B. - eine Ausnahme, die potenzielle Benutzereingriffe erkennt und mit einem Abmelde-GET zwangsweise zur Anmeldeseite umleitet ).

Joel Etherton
quelle
Interessant; Ich habe es nie so gesehen. +1.
Strager
Dies könnte möglicherweise von der Anwendung abhängen (eine Art "kaskadierendes Löschverhalten"), aber Sie haben Recht.
Andres Jaan Tack
@ JoelEtherton Danke Joel, ich habe die Antworten gelesen und mich gefragt, wann ich die richtige finden würde. :)
Kirill Fuchs
4
Es ist verwirrend, weil das Abmelden den Status ändert. POST ist das Verb zum Ändern des Zustands. GET dient zum Abrufen zustandsloser Daten. Es ist verwirrend, weil wir erwarten, dass POST-Anfragen Nutzdaten haben. Wie unten erwähnt, ist DELETE für ein Sitzungsobjekt am korrektesten.
Michael Cole
1
@ MichaelCole: Ich würde dieser Darstellung der Schwierigkeit zwischen POST und GET zustimmen. Ich würde der Verwendung des DELETE-Verbs jedoch nicht zustimmen. DELETE dient zum Behandeln einer Ressource, und die Sitzung ist in diesem Sinne keine Ressource. Überlegen Sie, ob Sie es LÖSCHEN können, wenn Sie es löschen können.
Joel Etherton
16

Hallo aus meiner Sicht, wenn Sie sich anmelden, überprüfen Sie Benutzername / Passwort und wenn diese übereinstimmen, erstellen Sie das Anmeldetoken.

CREAT-Token => Methode POST

Wenn Sie sich abmelden, zerstören Sie das Token, daher sollte für mich die logischste Methode ein LÖSCHEN sein

DELETE-Token => Methode DELETE

miorey
quelle
4
Interessanter Winkel.
Drumbeg
1
Ich verwende diese Methode in meinen Spring Boot REST-Anwendungen.
Please_Dont_Bully_Me_SO_Lords
1
semantisch korrekt. Ich stimme zu ...
DAG
1

Das Szenario des Pre-Caching ist interessant. Aber ich vermute, wenn sich viele Websites nicht darum kümmern, sollten Sie es vielleicht auch nicht tun.

Oder könnte der Link in Javascript implementiert werden?

Bearbeiten: Soweit ich weiß, sollte ein GET technisch für schreibgeschützte Anforderungen sein, die den Anwendungsstatus nicht ändern. Ein POST sollte für Schreib- / Bearbeitungsanforderungen sein, die den Status ändern. Andere Anwendungsprobleme bevorzugen jedoch möglicherweise GET gegenüber POST für einige Statusänderungsanforderungen, und ich glaube nicht, dass dies ein Problem darstellt.

Richard H.
quelle
Vielen Dank. Der DB- Status würde nicht geändert, der Sitzungsstatus jedoch. Das einzige Problem, das ich sehe, ist das, das ich in der Frage erwähnt habe, dass Benutzer rausgeschmissen werden. Zerstörungsfrei aber eher nervig. Normalerweise gehe ich auch nach dem Mantra "Wenn die großen Jungs es tun, dann muss es in Ordnung sein". Ich wollte nur wissen, welche Meinung andere dazu haben.
Daniel Liuzzi
0

Wenn Sie Ihre Webanwendung die Sitzung über ein Abmeldeskript abbrechen lassen, benötigen Sie dies normalerweise auch nicht. Normalerweise gibt es eine Sitzungsvariable, die für die Sitzung, die Sie abbrechen möchten, eindeutig ist.

rauben
quelle
Könnten Sie das "Abmeldeskript" ausarbeiten? Ich bin nicht sicher, ob Sie sich auf das Festlegen eines Cookie-Ablaufs beziehen (was nicht die Notwendigkeit beseitigt, Benutzer manuell abmelden zu lassen).
Daniel Liuzzi
Ein Abmeldeskript würde die Sitzung des Benutzers (eigentlich: Browser) beenden, der es aufruft. In ASP.net ist die Sitzung ein serverseitiges Objekt, das abgebrochen werden kann. PHP hat ein ähnliches System. Da dieser Browser das Skript aufruft, das die Sitzung beendet, weiß er bereits, welches zu beenden ist, sodass keine POST- oder GET-Variablen erforderlich sind.
Rob
1
Ja, ich verstehe dich jetzt. Ich habe das Skript bereits installiert, insbesondere FormsAuthentication.SignOut (), aber meine Frage ist, wie das Skript wie in GET oder POST aufgerufen wird.
Daniel Liuzzi
Oh du hast die URL in einer Form? Es spielt keine Rolle, ob Sie keine Informationen an ihn weitergeben. Das Schlimmste, was passieren kann, ist, dass jemand das Skript manuell öffnet und sich abmeldet. Ich würde es nicht einmal zu einem Formularfeld machen, wenn es nicht notwendig wäre. Ein Link zum Skript würde ebenfalls funktionieren. Wenn Sie Informationen an das Skript senden, würde ich wahrscheinlich einen POST durchführen, um dem Benutzer keine Informationen anzuzeigen (es sei denn, er zeigt die Seitenquelle an), und wenn er aktualisiert wird, erhält er eine Warnung von seinem Browser (Seite abgelaufen), was wünschenswert sein könnte.
Rob
0

Vor kurzem habe ich an einem Projekt gearbeitet, bei dem ich mich mit GET abmelde. Nachfolgend finden Sie den Code in Nodejs Express, der einwandfrei funktioniert

Ihre router.js

const express = require("express");
router.get("/signout", signout);

Ihr controller.js

exports.signout  = (req, res) => {
        res.clearCookie('t'); //clearing cookie, which is 
            //assign to the user during sign in.          
            res.json({message : 'Signout success'});   
        };
xSachinx
quelle
-2

Ich sehe nicht, wie das Abmelden (Erhöhen der Benutzerberechtigungen) eine zerstörerische Aktion ist. Dies liegt daran, dass die Aktion "Abmelden" nur für Benutzer verfügbar sein sollte, die bereits angemeldet sind. Andernfalls wäre sie veraltet.

Eine zufällig generierte Zeichenfolge in Ihren Browser-Cookies repräsentiert Ihre Benutzersitzung. Es gibt unzählige Möglichkeiten, es zu zerstören. Eine effektive Abmeldung ist lediglich ein Service für Ihren Besucher.

jpluijmers
quelle
2
wgetIm Spider-Modus mit einem korrekten Sitzungscookie in einem privaten Wiki musste ich das eigentlich einmal machen. Natürlich war eine der ersten gecrawlten URLs /logout.
Helgi
5
Besuchen Sie SuperLogout.com, um zu sehen, wie zerstörerisch GET-Anforderungen an /logoutSeiten wirklich sind. Sie müssen sich beispielsweise erneut bei Google Mail anmelden, sich erneut beim Chat anmelden, Ihren Platz in Hangouts-Konversationen finden, die Sie gescrollt haben usw. - und dies gilt nur für Google.com.
Dan Dascalescu