Logout: OTTIENI o POST?


435

Questa domanda non riguarda quando utilizzare GET o POST in generale; si tratta di quale è quella consigliata per la gestione della disconnessione da un'applicazione web. Ho trovato molte informazioni sulle differenze tra GET e POST in senso generale, ma non ho trovato una risposta definitiva per questo particolare scenario.

Come pragmatico, sono propenso a usare GET, perché implementarlo è molto più semplice di POST; rilascia un semplice link e il gioco è fatto. Questo sembra essere il caso della stragrande maggioranza dei siti Web a cui riesco a pensare, almeno dalla cima della mia testa. Anche Stack Overflow gestisce la disconnessione con GET.

La cosa che mi fa esitare è l'argomentazione (sebbene vecchia) secondo cui alcuni acceleratori / proxy web pre-memorizzano le pagine andando e recuperando tutti i collegamenti che trovano nella pagina, in modo che l'utente ottenga una risposta più veloce quando fa clic su di essi. Non sono sicuro che ciò si applichi ancora, ma se fosse così, in teoria un utente con uno di questi acceleratori verrebbe espulso dall'applicazione non appena accedeva, perché il suo acceleratore avrebbe trovato e recuperato il logout link anche se non ci ha mai cliccato sopra.

Tutto ciò che ho letto finora suggerisce che il POST dovrebbe essere usato per "azioni distruttive", mentre le azioni che non alterano lo stato interno dell'applicazione - interrogazioni simili e simili - dovrebbero essere gestite con GET . Sulla base di questo, la vera domanda qui è:

La disconnessione da un'applicazione è considerata un'azione distruttiva / modifica lo stato interno dell'applicazione?


Bene, supponendo che tu stia visitando il sito per la prima volta e che il link di logout non sia presente, verrai disconnesso al momento del login. Andrebbe bene dopo aver effettuato l'accesso una seconda volta, poiché l'URL di disconnessione è già memorizzato nella cache. Ma si può presumere che qualsiasi acceleratore decente sarebbe in grado di filtrare la maggior parte degli URL di disconnessione.
HyperCas,

2
HyperCas, gli acceleratori che filtravano gli URL di logout era una teoria che stavo prendendo in considerazione e uno dei motivi per cui ho deciso di pubblicare la domanda. Mi sento un po 'riluttante a fidarmi solo della logica dell'acceleratore e un giorno un utente con un acceleratore schifoso si lamenta di non poter accedere. Sai se seguono uno standard o se tale standard esiste?
Daniel Liuzzi,

Qualsiasi acceleratore che ha inviato automaticamente un modulo (ad esempio) sarebbe un malware IMO ... è assolutamente illogico pensare che un acceleratore invii automaticamente un modulo. Immagina di visitare Google. Come ha potuto inviare il modulo di ricerca? Nessuno può spiegare il malware in quanto è troppo imprevedibile e non segue le regole.
Alex,

3
@AlexW - Penso che tu abbia frainteso la mia domanda. Lo scenario dell'acceleratore che ho proposto è quello di mostrare un possibile problema quando si utilizza GET, non POST, quindi non ci sarebbe alcuna forma da pubblicare, solo semplici collegamenti che gli acceleratori non avrebbero avuto problemi a seguire.
Daniel Liuzzi,

1
Mi rendo conto di essere in ritardo di anni per questo, ma Alex, non è quello che Daniel sta chiedendo. Sta dicendo che se un utente fa clic su un collegamento di logout e un acceleratore restituisce la pagina di logout nella cache senza che colpisca l'applicazione, l'utente rimarrebbe connesso. Niente a che fare con il malware, anche se FYI che controlla una stringa User-Agent non si aggiusta qualsiasi cosa comunque.
Rob Grant,

Risposte:


476

Usa POST.

Nel 2010, l'utilizzo GETera probabilmente una risposta accettabile. Ma oggi (nel 2013), i browser pre-recupereranno le pagine che "pensano" che visiterai in seguito.

Ecco uno degli sviluppatori StackOverflow che parla di questo problema su Twitter:

Vorrei ringraziare la mia banca per aver effettuato la disconnessione da una richiesta GET e il team di Chrome per il comodo prefetching dell'URL. - Nick Craver ( @Nick_Craver ) 29 gennaio 2013

fatto curioso: StackOverflow usato per gestire il log-out tramite GET, ma non più.


2
Grazie per questo aggiornamento, Dave. Non ho nemmeno notato che SO ha cambiato il loro logout in POST, e onestamente non avevo idea che Chrome fosse dotato di pre-fetching integrato. Infine, il twit che hai citato non avrebbe mai potuto offrire un esempio migliore al problema che ho descritto nel mio la mia domanda e conferma i miei sospetti. Sto votando la tua risposta e rendendola la risposta accettata.
Daniel Liuzzi,

4
Nel mio browser, il logout Stackoverflow sembra <li> <a href="https://stackoverflow.com/users/logout"> disconnettersi </a> </li> che è un GET, non un POST
boatcoder,

9
@ Mark0978, fai clic sul collegamento.
David Murdoch,

2
Interessante. Questa è probabilmente una delle mie funzioni meno preferite, un logout che poi mi chiede se ne sono sicuro. Suppongo che impedisce al prefetch di disconnettersi, ma Amazon, Ebay e Gmail usano tutti GET per la disconnessione senza quella pagina di trucco tra ciò che viene detto all'utente è la disconnessione e l'evento di disconnessione effettivo. Immagino che tra una pagina e l'altra si verificherebbe che molte persone credono erroneamente di essere disconnesse. I problemi con questo su SO sono minimi, senza soldi, e comunque il 99% di tutto è pubblico.
Boatcoder

7
@Red Secondo lo standard HTTP / 1.1, questo è un errore del server, non del browser. Si prevede che GET non abbia effetti collaterali sul lato server. Lo standard dice anche "l'utente non ha richiesto gli effetti collaterali, quindi non può essere ritenuto responsabile per loro".
eyuelt,

45

In REST non ci dovrebbero essere sessioni, quindi non c'è nulla da distruggere. Un client REST si autentica su ogni richiesta. Connesso o disconnesso, è solo un'illusione.

Quello che stai veramente chiedendo è se il browser continua a inviare le informazioni di autenticazione su ogni richiesta.

Probabilmente, se la tua applicazione crea l'illusione di essere loggato, dovresti essere in grado di "disconnetterti" usando javascript. Nessun viaggio di andata e ritorno richiesto.


Tesi di fielding - Sezione 5.1.3

ogni richiesta dal client al server deve contenere tutte le informazioni necessarie per comprendere la richiesta e non può sfruttare alcun contesto memorizzato sul server. Lo stato della sessione viene quindi mantenuto interamente sul client


1
In realtà non ne ero a conoscenza. Quindi suppongo che la mia app non sarà affatto RESTful, poiché sto usando ASP.NET MVC con FormsAuthentication e si basa su sessioni ...
Daniel Liuzzi,

19
ma in pratica le informazioni di accesso sono conservate in un cookie contrassegnato con l' httponlyattributo per prevenire alcuni rischi xss, il che significa che può essere ripristinato solo dal server (a meno di cancellare manualmente il cookie)
Remus Rusanu

6
"Manuale" come nell'utente passa alle impostazioni del browser e sceglie l'opzione "Cancella cookie". Difficilmente un modo accettabile per "disconnettersi" da un sito web.
Remus Rusanu,

1
@Remus Ahhh, come l'illustre browser web rende la scrittura di app Web così dolorosa.
Darrel Miller,

1
@DarrelMiller sì, tuttavia, non revocare un JWT sul lato server è una vulnerabilità di sicurezza. Anche se i token non sono memorizzati sul server, dovrebbero essere inseriti nella lista nera quando un utente si disconnette / cambia password / cambia ruoli / esce / ecc. Per prevenire abusi (almeno fino alla loro scadenza).
java-addict301,

39

Un modo GETpotrebbe essere abusato qui è che una persona (forse un concorrente :) ha inserito un tag immagine con src="<your logout link>"OVUNQUE su Internet e se un utente del tuo sito si imbatte in quella pagina, verrà disconnesso inconsapevolmente.


4
No, non è giusto. Un collegamento di disconnessione funzionerà solo se vengono inviati i dati cookie corretti, che non provengono da un altro dominio. E anche se l'ID di sessione è archiviato nell'URL, non funzionerebbe neanche perché cambiano per ogni sessione.
Richard H,

4
Caspita, non ci avevo mai pensato! Quindi, un altro motivo per non usare GET e un altro motivo per cui non capisco perché lo facciano tutti. Dannazione, ora sto temped di includere uno stackoverflow.com/users/logout "immagine" troppo il mio post e vedere cosa succede :-D
Daniel Liuzzi

24
src = è una semplice richiesta del browser, non proviene dal lato server, ma dal client. Contiene tutti i cookie e proviene dall'IP dell'utente. Ecco perché i pixel di tracciamento degli annunci funzionano. L'unico modo per determinare tale exploit sarebbe controllare il referrer.
Raveren,

12
SuperLogout.com fa esattamente questo (carica gli /logoutURL in immagini nascoste) e funziona.
Dan Dascalescu,

9
ri: SuperLogout ... Non so perché l'ho cliccato.
MI Wright il

21

Per essere corretti, GET / POST (o altri verbi) sono azioni su alcune risorse (indirizzate dall'URL), quindi generalmente riguardano lo stato della risorsa e non lo stato dell'applicazione in quanto tale. Quindi, nel vero spirito, dovresti avere un URL come [host name]\[user name]\session, quindi 'ELIMINA' sarebbe il verbo corretto per l'azione di disconnessione.

Utilizzando [host name]\bla bla\logoutcome URL in realtà non un REST full way (IMO), quindi perché discutere sul corretto uso di GET / POST su di esso?

Naturalmente, utilizzo anche GET per un URL di logout nelle mie applicazioni :-)


2
In quel caso, avrei allora sostenere che avendo il [nome utente] parte nell'URL sembra inutile, in quanto gli utenti sempre il logout da (cioè DELETE) la propria sessione; mai gli altri utenti :-)
Daniel Liuzzi

1
Non proprio - stiamo dicendo che la sessione è una risorsa e vogliamo eliminarla. Quindi, per indirizzare in modo uniforme qualsiasi sessione, devi avere il nome utente come parte dell'URL. Il tuo argomento è buono come dire che lanciare un'azione PUT su [galleria fotografica] \ immagini significa che stai aggiungendo alle tue foto (disponibile in [galleria fotografica] \ [nome utente] \ immagini). Diverse risorse devono essere indirizzate esplicitamente, non ci possono essere implicazioni in esso. Il sito potrebbe consentire ad altri utenti di aggiungere immagini alla tua galleria: farebbe parte del controllo degli accessi così come puoi avere un super utente che può uccidere le sessioni di chiunque.
VinayC,

1
Filosoficamente parlando, potresti chiamare sessioni e fotografie "risorse", ma realisticamente non le tratterei allo stesso modo. Le sessioni sono sempre intrinsecamente limitate all'utente corrente (da cui il nome Sessione) e, almeno in ASP.NET, non è possibile accedere alle sessioni di un altro utente. Perfino lo sviluppatore dell'applicazione non ha un modo diretto di enumerare tutte le sessioni attive o mezzi per uccidere le sessioni individualmente. Potresti riavviare l'applicazione per terminare tutte le sessioni (InProc), ma non chiamerei questo controllo di accesso. A parte gli URL, la domanda rimane ancora: GET o POST?
Daniel Liuzzi,

Le risorse, quindi il suo indirizzo (URL) sono parte importante di REST. Quindi, se scegli l'URL come ho detto, DELETE diventa la parola corretta, non GET o POST. Inoltre, anche se ti stai limitando ad ASP.NET, puoi sempre avere il tuo provider di stato personalizzato che può darti il ​​modo di enumerare le sessioni e uccidere altre sessioni se necessario. Per le sessioni in-out out-of-box, alcuni armeggi in global.asax dovrebbero darti la funzionalità. È davvero una questione se tale funzionalità sarebbe necessaria o meno. Per esigenze rare, la gente tende a riavviare il sito Web per cacciare le persone fuori dal sito.
VinayC,

Questo ha più senso per me. Dai al web api un percorso di sessione e chiama DELETE su di esso. Sia che ../session o ../session/current. Thankx @VinayC
Simon Hooper

16

La disconnessione non fa nulla per l'applicazione stessa. Cambia lo stato dell'utente in relazione all'applicazione. In questo caso, sembra che la tua domanda sia più basata sul modo in cui il comando deve essere avviato dall'utente per iniziare questa azione. Poiché questa non è "un'azione distruttiva", è certo che la sessione sia stata abbandonata o distrutta ma che né l'applicazione né i dati siano stati modificati, non è possibile consentire ad entrambi i metodi di avviare una procedura di disconnessione. Il post deve essere utilizzato da tutte le azioni avviate dall'utente (ad es. - l'utente fa clic su "Esci"), mentre get potrebbe essere riservato per le disconnessioni avviate dall'applicazione (ad esempio - un'eccezione che rileva la potenziale intrusione dell'utente reindirizza forzatamente alla pagina di accesso con una disconnessione GET ).


Interessante; Non ci ho mai pensato in questo modo. +1.
Strager

Ciò potrebbe dipendere in modo plausibile dall'applicazione (una sorta di comportamento di "eliminazione a cascata"), ma hai ragione.
Andres Jaan Tack,

@JoelEtherton Grazie Joel, stavo leggendo le risposte chiedendomi quando sarei arrivato a quello giusto. :)
Kirill Fuchs

4
È confuso perché il logout cambia stato. POST è il verbo per cambiare stato. GET è per ottenere dati senza stato. È confuso perché prevediamo che le richieste POST abbiano payload. Come indicato di seguito, DELETE sarebbe più corretto su un oggetto sessione.
Michael Cole,

1
@MichaelCole: concordo con quella rappresentazione della difficoltà tra POST e GET. Non sarei d'accordo con l'uso del verbo DELETE, comunque. DELETE serve per gestire una risorsa e la sessione non è una risorsa in questo senso. Considera, se puoi ELIMINARLO, dovresti anche essere in grado di METTERE.
Joel Etherton,

16

Ciao dal mio punto di vista, quando accedi controlla nome utente / password e se quelli sono corrispondenti crei il token di accesso.

Token CREAT => metodo POST

Quando esci, devi distribuire il token, quindi per me il metodo più logico dovrebbe essere un DELETE

Token DELETE => metodo DELETE


4
Angolo interessante.
Drumbeg

1
Uso questo metodo nelle mie applicazioni REST di Spring Boot.
Please_Dont_Bully_Me_SO_Lords,

1
semanticamente corretto. Sono d'accordo ...
DAG,

1

Lo scenario di pre-cache è interessante. Ma suppongo che se molti siti, tra cui SO, non si preoccupano di questo, forse non dovresti farlo neanche tu.

O forse il link potrebbe essere implementato in javascript?

Modifica: a quanto ho capito, tecnicamente un GET dovrebbe essere per le richieste di sola lettura, che non cambiano lo stato dell'applicazione. Un POST dovrebbe essere per le richieste di scrittura / modifica che cambiano stato. Tuttavia, altri problemi relativi all'applicazione potrebbero preferire GET rispetto a POST per alcune richieste che cambiano stato e non credo che ci siano problemi.


Grazie. Lo stato del DB non verrebbe modificato, ma lo stato della sessione . L'unico problema che vedo è quello che ho citato nella domanda, riguardo agli utenti che vengono espulsi. Non distruttivo ma piuttosto fastidioso. Di solito vado anche dal mantra "se i grandi ragazzi lo fanno, allora deve essere OK". Volevo solo sapere quale opinione hanno gli altri su questo.
Daniel Liuzzi,

0

Bene, se lasci che la tua applicazione web lasci la sessione attraverso uno script di logout, di solito non ti serve neanche. Normalmente esiste una variabile di sessione unica per la sessione che si desidera abbandonare.


Potresti elaborare lo "script di logout"? Non sono sicuro se ti riferisci all'impostazione di una scadenza dei cookie (che non elimina la necessità di un modo per consentire agli utenti di disconnettersi manualmente).
Daniel Liuzzi

Uno script di disconnessione termina la sessione dell'utente (in realtà: browser) che lo chiama. In ASP.net, la sessione è un oggetto lato server che può essere abbandonato. PHP ha un sistema simile. Poiché quel browser chiama lo script che termina la sessione, sa già quale terminare, eliminando la necessità di variabili POST o GET.
Rob,

1
Sì, ti capisco adesso. Ho già installato lo script, in particolare FormsAuthentication.SignOut (), ma la mia domanda è su come invocare lo script, come in GET o POST.
Daniel Liuzzi,

Oh hai l'URL in una forma? Non importa se non ci stai trasmettendo alcuna informazione. La cosa peggiore che potrebbe accadere è che qualcuno apra manualmente lo script, disconnettendosi. Non lo farei nemmeno un campo modulo se non fosse necessario, anche un collegamento allo script funzionerebbe. Se invii informazioni allo script, probabilmente sceglierei un POST, in modo da non mostrare alcuna informazione all'utente (a meno che non visualizzino l'origine della pagina) e se si aggiornano riceveranno un avviso dal loro browser (pagina scaduta), che potrebbe essere desiderabile.
Rob,

0

Recentemente stavo lavorando a un progetto che utilizzo GET per disconnettersi Di seguito è riportato il codice in Nodejs Express e funziona perfettamente

il tuo router.js

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

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'});   
        };

-2

Non vedo come disconnettersi (deselezionare le autorizzazioni utente) sia un'azione descrittiva. Questo perché l'azione "disconnessione" dovrebbe essere disponibile solo per gli utenti che hanno già effettuato l'accesso altrimenti sarebbe obsoleta.

Una stringa generata in modo casuale contenuta nei cookie del browser rappresenta tutti la sessione dell'utente. Esistono molti modi per distruggerlo, quindi la disconnessione in modo efficace è semplicemente un servizio per il tuo visitatore.


2
wgetin modalità spider con un cookie di sessione corretto su un wiki privato era una cosa che in realtà dovevo fare una volta. Naturalmente, uno dei primi URL sottoposti a scansione è stato /logout.
Helgi,

5
Prova ad andare su SuperLogout.com per vedere quanto /logoutsono davvero distruttive le richieste GET alle pagine. Ad esempio, dovrai accedere di nuovo a Gmail, accedere di nuovo alla chat, trovare il tuo posto in tutte le conversazioni di Hangouts che hai fatto scorrere ecc. - E questo è solo per Google.com.
Dan Dascalescu,
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.