Déconnexion: GET ou POST?

435

Cette question ne concerne pas quand utiliser GET ou POST en général; il s'agit de celui qui est recommandé pour gérer la déconnexion d'une application Web. J'ai trouvé beaucoup d'informations sur les différences entre GET et POST dans le sens général, mais je n'ai pas trouvé de réponse définitive pour ce scénario particulier.

En tant que pragmatique, je suis enclin à utiliser GET, car sa mise en œuvre est beaucoup plus simple que POST; déposez simplement un lien simple et vous avez terminé. Cela semble être le cas avec la grande majorité des sites Web auxquels je peux penser, au moins du haut de ma tête. Même Stack Overflow gère la déconnexion avec GET.

Ce qui me fait hésiter, c'est l'argument (quoique ancien) selon lequel certains accélérateurs / mandataires Web pré-cachent les pages en allant récupérer tous les liens qu'ils trouvent dans la page, afin que l'utilisateur reçoive une réponse plus rapide lorsqu'il clique dessus. Je ne sais pas si cela s'applique toujours, mais si c'était le cas, alors en théorie, un utilisateur avec l'un de ces accélérateurs serait expulsé de l'application dès qu'elle se connecterait, car son accélérateur trouverait et récupérerait la déconnexion lien même si elle n'a jamais cliqué dessus.

Tout ce que j'ai lu jusqu'à présent suggère que POST devrait être utilisé pour des "actions destructrices", alors que les actions qui ne modifient pas l'état interne de l'interrogation de type application et autres devraient être traitées avec GET . Sur cette base, la vraie question ici est:

La déconnexion d'une application est-elle considérée comme une action destructrice / modifie-t-elle l'état interne de l'application?

Daniel Liuzzi
la source
Eh bien, en supposant que vous visitez le site pour la première fois et que le lien de déconnexion n'est pas présent, vous serez déconnecté lorsque vous vous connecterez. Ce serait bien après vous être connecté une deuxième fois, car l'URL de déconnexion est déjà mise en cache. Mais on peut supposer que n'importe quel accélérateur décent serait capable de filtrer la plupart des URL de déconnexion.
HyperCas
2
HyperCas, les accélérateurs filtrant les URL de déconnexion était une théorie que j'envisageais et l'une des raisons pour lesquelles j'ai décidé de poser la question. Je suis un peu réticent à faire confiance à la logique de l'accélérateur, et un jour, un utilisateur avec un accélérateur merdique se plaindra de ne pas pouvoir se connecter. Savez-vous s'ils respectent une norme ou si une telle norme existe?
Daniel Liuzzi
Tout accélérateur qui soumettrait automatiquement un formulaire (par exemple) serait un logiciel malveillant IMO ... il est totalement illogique de penser qu'un accélérateur soumettrait un formulaire automatiquement. Imaginez que vous visitez Google. Comment pourrait-il soumettre le formulaire de recherche? Personne ne peut rendre compte des logiciels malveillants car ils sont trop imprévisibles et ne respectent pas les règles.
Alex
3
@AlexW - Je pense que vous avez mal compris ma question. Le scénario d'accélérateur que j'ai proposé est de montrer un problème possible lors de l'utilisation de GET, pas de POST, donc il n'y aurait pas de formulaire à publier, seulement des liens simples que les accélérateurs n'auraient aucun problème à suivre.
Daniel Liuzzi
1
Je réalise que je suis trop tard pour ça, mais Alex, ce n'est pas ce que Daniel demande. Il dit que si un utilisateur clique sur un lien de déconnexion et qu'un accélérateur retourne la page de déconnexion mise en cache sans qu'il ne frappe l'application, alors l'utilisateur resterait connecté. Rien à voir avec les logiciels malveillants, bien que FYI vérifiant une chaîne User-Agent ne puisse pas réparer quoi que ce soit de toute façon.
Rob Grant

Réponses:

476

Utilisez POST.

En 2010, l'utilisation GETétait probablement une réponse acceptable. Mais aujourd'hui (en 2013), les navigateurs prélèveront les pages qu'ils "pensent" que vous visiterez ensuite.

Voici l'un des développeurs de StackOverflow parlant de ce problème sur Twitter:

Je tiens à remercier ma banque pour avoir déconnecté une demande GET et l'équipe Chrome pour la préchargement pratique des URL.- Nick Craver ( @Nick_Craver ) 29 janvier 2013

fait amusant: StackOverflow était utilisé pour gérer la déconnexion via GET, mais plus maintenant.

David Murdoch
la source
2
Merci pour cette mise à jour, Dave. Je n'ai même pas remarqué que SO a changé sa connexion à POST, et je n'avais honnêtement aucune idée que Chrome est livré avec la pré-récupération intégrée. Enfin, le twit que vous avez cité n'aurait jamais pu offrir un meilleur exemple du problème que j'ai décrit dans mon ma question et confirme mes soupçons. Je vote pour votre réponse et j'en fais la réponse acceptée.
Daniel Liuzzi
4
Dans mon navigateur, la déconnexion Stackoverflow ressemble à la <li> <a href="https://stackoverflow.com/users/logout"> déconnexion </a> </li> qui est un GET, pas un POST
boatcoder
9
@ Mark0978, cliquez sur le lien.
David Murdoch
2
Intéressant. C'est probablement l'une de mes fonctionnalités les moins préférées, une déconnexion qui me demande ensuite si je suis sûr. Je suppose que cela empêche la prélecture de vous déconnecter, mais Amazon, Ebay et Gmail utilisent tous GET pour la déconnexion sans que cette page astucieuse entre ce qui est dit à l'utilisateur est la déconnexion et l'événement de déconnexion réel. J'imagine qu'entre les pages, beaucoup de gens croient à tort qu'ils ont été déconnectés. Les problèmes avec cela sur SO sont minimes, pas d'argent impliqué, et 99% de tout est public de toute façon.
Boatcoder du
7
@Red Selon la norme HTTP / 1.1, c'est la faute du serveur, pas celle du navigateur. GET ne devrait avoir aucun effet secondaire du côté serveur. La norme dit même que "l'utilisateur n'a pas demandé les effets secondaires, il ne peut donc pas en être tenu responsable".
eyuelt
45

Dans REST, il ne devrait pas y avoir de session, il n'y a donc rien à détruire. Un client REST s'authentifie à chaque demande. Connecté ou déconnecté, ce n'est qu'une illusion.

Ce que vous demandez vraiment, c'est si le navigateur continue d'envoyer les informations d'authentification à chaque demande.

Sans doute, si votre application crée l'illusion d'être connecté, vous devriez pouvoir vous "déconnecter" en utilisant javascript. Aucun aller-retour requis.


Dissertation sur le terrain - Section 5.1.3

chaque demande du client au serveur doit contenir toutes les informations nécessaires à la compréhension de la demande et ne peut profiter d'aucun contexte stocké sur le serveur. L'état de la session est donc entièrement conservé sur le client

Darrel Miller
la source
1
En fait, je n'étais pas au courant de cela. Ensuite, je suppose que mon application ne sera pas du tout RESTful, car j'utilise ASP.NET MVC avec FormsAuthentication et elle repose sur des sessions ...
Daniel Liuzzi
19
mais en pratique, les informations de connexion sont conservées dans un cookie marqué avec l' httponlyattribut pour éviter certains risques xss, ce qui signifie qu'elles ne peuvent être réinitialisées qu'à partir du serveur (à moins d'effacer manuellement le cookie)
Remus Rusanu
6
«Manuel» comme dans l'utilisateur va dans les paramètres du navigateur et choisit l'option «Effacer les cookies». Ce n'est pas une façon acceptable de se déconnecter d'un site Web.
Remus Rusanu
1
@Remus Ahhh, comment l'illustre navigateur Web rend l'écriture d'applications Web si pénible.
Darrel Miller
1
@DarrelMiller oui mais ne pas révoquer un JWT côté serveur est une vulnérabilité de sécurité. Même si les jetons ne sont pas stockés sur le serveur, ils doivent être mis sur liste noire lorsqu'un utilisateur se déconnecte / change de mot de passe / change de rôle / quitte / etc pour éviter les abus (au moins jusqu'à leur expiration).
java-addict301
39

Une façon GETpourrait être abusée ici est qu'une personne (un concurrent peut-être :) a placé une balise d'image avec src="<your logout link>"N'IMPORTE O, sur Internet, et si un utilisateur de votre site tombe sur cette page, il sera déconnecté sans le savoir.

raveren
la source
4
Non, ce n'est pas vrai. Un lien de déconnexion ne fonctionnera que si les données de cookie correctes sont envoyées, ce qui ne proviendra pas d'un autre domaine. Et même si l'ID de session est stocké dans l'URL, cela ne fonctionnera pas non plus car ceux-ci changent pour chaque session.
Richard H
4
Wow, je n'y ai jamais pensé! Alors là, une autre raison de ne pas utiliser GET, et une autre raison pour laquelle je ne comprends pas pourquoi tout le monde le fait. Bon sang, maintenant je suis tenté d'inclure une "image" stackoverflow.com/users/logout aussi mon post et voir ce qui se passe :-D
Daniel Liuzzi
24
src = est une simple requête de navigateur, elle ne vient pas du côté serveur, mais du client. Il contient tous les cookies et provient de l'adresse IP de l'utilisateur. C'est pourquoi les pixels de suivi des annonces fonctionnent. La seule façon de déterminer un tel exploit serait de vérifier le référent.
raveren
12
SuperLogout.com fait exactement cela (charger les /logoutURL dans des images cachées), et cela fonctionne.
Dan Dascalescu
9
re: SuperLogout ... Je ne sais pas pourquoi j'ai cliqué dessus.
MI Wright
21

Pour être correct, GET / POST (ou d'autres verbes) sont des actions sur une ressource (adressée par URL) - donc c'est généralement sur l'état de la ressource et non sur l'état de l'application en tant que tel. Donc, dans les vrais esprits, vous devriez avoir une URL telle que [host name]\[user name]\session, alors 'SUPPRIMER' serait le verbe correct pour l'action de déconnexion.

L'utilisation en [host name]\bla bla\logouttant qu'URL n'est pas vraiment un moyen complet REST (IMO), alors pourquoi débattre de l'utilisation correcte de GET / POST dessus?

Bien sûr, j'utilise également GET pour une URL de déconnexion dans mes applications :-)

VinayC
la source
2
Dans ce cas, je dirais alors qu'avoir la partie [nom d'utilisateur] dans l'URL semble inutile, car les utilisateurs se déconnectent toujours (c'est-à-dire SUPPRIMENT) de leur propre session; jamais d'autres utilisateurs :-)
Daniel Liuzzi
1
Pas vraiment - nous disons que la session est une ressource et nous voulons la supprimer. Donc, pour adresser uniformément n'importe quelle session, vous devez avoir un nom d'utilisateur comme partie de l'URL. Votre argument revient à dire que l'émission d'une action PUT sur [gallerie de photos] \ images signifie que vous ajoutez à vos photos (disponible dans [gallerie de photos] \ [nom d'utilisateur] \ images). Différentes ressources doivent être abordées de manière explicite, il ne peut y avoir aucune implication. Le site peut permettre à d'autres utilisateurs d'ajouter des photos à votre galerie - cela ferait partie du contrôle d'accès tout comme vous pouvez avoir un super utilisateur qui peut tuer les sessions de n'importe qui.
VinayC
1
Philosophiquement parlant, vous pourriez appeler des sessions et des photos «ressources», mais en réalité, je ne les traiterais pas de la même manière. Les sessions sont toujours intrinsèquement limitées à l'utilisateur actuel (d'où le nom Session) et, au moins dans ASP.NET, il n'y a aucun moyen d'accéder aux sessions d'un autre utilisateur. Même le développeur de l'application n'a aucun moyen direct d'énumérer toutes les sessions actives, ni de supprimer les sessions individuellement. Vous pouvez redémarrer l'application pour tuer toutes les sessions (InProc), mais je n'appellerais pas ce contrôle d'accès. Mis à part les URL, la question demeure: GET ou POST?
Daniel Liuzzi
La ressource, d'où son adresse (URL), est une partie importante de REST. Donc, si vous choisissez URL comme je l'ai dit, SUPPRIMER devient le mot correct - et non GET ou POST. De plus, même si vous vous limitez à ASP.NET, vous pouvez toujours avoir votre fournisseur d'état personnalisé qui peut vous permettre d'énumérer les sessions et de tuer d'autres sessions si nécessaire. Pour les sessions in-process in-box, quelques bidouilles dans global.asax devraient vous donner la fonctionnalité. C'est vraiment une question de savoir si une telle fonctionnalité serait nécessaire ou non. Pour les besoins peu fréquents, les gens ont tendance à redémarrer le site Web pour expulser les gens du site.
VinayC
Cela a le plus de sens pour moi. Donnez à l'API Web un itinéraire de session et appelez DELETE dessus. Que ce soit ../session ou ../session/current. Thankx @VinayC
Simon Hooper
16

La déconnexion n'a aucun effet sur l'application elle-même. Il modifie l'état de l'utilisateur par rapport à l'application. Dans ce cas, il semble que votre question soit davantage basée sur la façon dont la commande doit être lancée par l'utilisateur pour commencer cette action. Comme il ne s'agit pas d'une "action destructrice", bien sûr que la session est abandonnée ou détruite mais que ni votre application ni vos données ne sont modifiées, il n'est pas impossible d'autoriser les deux méthodes à lancer une procédure de déconnexion. La publication doit être utilisée par toutes les actions initiées par l'utilisateur (par exemple - l'utilisateur clique sur "Déconnexion"), tandis que get peut être réservé aux déconnexions initiées par l'application (par exemple - une exception détectant une intrusion potentielle de l'utilisateur redirige de force vers la page de connexion avec une déconnexion GET ).

Joel Etherton
la source
Intéressant; Je n'y ai jamais pensé de cette façon. +1.
strager
Cela pourrait en théorie dépendre de l'application (une sorte de comportement de "suppression en cascade"), mais vous avez raison.
Andres Jaan Tack
@JoelEtherton Merci Joel, je lisais les réponses en me demandant quand j'arriverais à la bonne. :)
Kirill Fuchs
4
C'est déroutant car la déconnexion change d'état. POST est le verbe pour changer d'état. GET sert à obtenir des données sans état. C'est déroutant car nous nous attendons à ce que les requêtes POST aient des charges utiles. Comme indiqué ci-dessous, DELETE serait plus correct sur un objet de session.
Michael Cole
1
@MichaelCole: Je serais d'accord avec cette représentation de la difficulté entre POST et GET. Cependant, je ne serais pas d'accord avec l'utilisation du verbe DELETE. DELETE sert à gérer une ressource et la session n'est pas une ressource dans ce sens. Considérez que si vous pouvez le SUPPRIMER, vous devriez également pouvoir le METTRE.
Joel Etherton
16

Bonjour de mon point de vue, lorsque vous vous connectez, vous vérifiez le nom d'utilisateur / mot de passe et si ceux-ci correspondent, vous créez le jeton de connexion.

Jeton CREAT => méthode POST

Lorsque vous vous déconnectez, vous détruisez le jeton, donc pour moi, la méthode la plus logique devrait être un SUPPRIMER

DELETE token => méthode DELETE

miorey
la source
4
Angle intéressant.
Drumbeg
1
J'utilise cette méthode dans mes applications Spring Boot REST.
Please_Dont_Bully_Me_SO_Lords
1
sémantiquement correct. Je suis d'accord ...
DAG
1

Le scénario de pré-mise en cache est intéressant. Mais je suppose que si de nombreux sites ne vous inquiètent pas, vous ne devriez peut-être pas non plus.

Ou peut-être que le lien pourrait être implémenté en javascript?

Edit: Si je comprends bien, techniquement, un GET devrait être pour les demandes en lecture seule, qui ne changent pas l'état de l'application. Un POST doit être destiné aux demandes d'écriture / modification qui changent d'état. Cependant, d'autres problèmes d'application pourraient préférer GET à POST pour certaines demandes de changement d'état, et je ne pense pas qu'il y ait de problème avec cela.

Richard H
la source
Merci. L' état de la base de données ne serait pas modifié, mais l' état de la session le serait. Le seul problème que je vois est celui que j'ai mentionné dans la question, à propos des utilisateurs expulsés. Non destructif mais plutôt ennuyeux. J'ai l'habitude de suivre le mantra «si les gros gars le font, alors ça doit être OK» aussi. Je voulais juste savoir quelle opinion les autres ont à ce sujet.
Daniel Liuzzi
0

Eh bien, si vous laissez votre application Web abandonner la session via un script de déconnexion, vous n'avez généralement pas besoin non plus. Normalement, il existe une variable de session unique pour la session que vous souhaitez abandonner.

Rob
la source
Pourriez-vous élaborer le "script de déconnexion"? Je ne sais pas si vous faites référence à la définition d'une expiration de cookie (ce qui n'élimine pas la nécessité de laisser les utilisateurs se déconnecter manuellement.)
Daniel Liuzzi
Un script de déconnexion mettrait fin à la session de l'utilisateur (en fait: navigateur) l'appelant. Dans ASP.net, la session est un objet côté serveur qui peut être abandonné. PHP a un système similaire. Étant donné que ce navigateur appelle le script qui met fin à la session, il sait déjà lequel terminer, ce qui élimine le besoin de variables POST ou GET.
Rob
1
Oui, je vous comprends maintenant. J'ai déjà le script en place, en particulier FormsAuthentication.SignOut (), mais ma question est de savoir comment appeler le script, comme dans GET ou POST.
Daniel Liuzzi
Oh, vous avez l'URL sous une forme? Peu importe que vous ne lui transmettiez aucune information. La pire chose qui puisse arriver est que quelqu'un ouvre manuellement le script et se déconnecte. Je n'en ferais même pas un champ de formulaire sinon nécessaire, un lien vers le script fonctionnerait également. Si vous envoyez des informations au script, j'opterais probablement pour un POST, afin de ne montrer aucune information à l'utilisateur (à moins qu'il ne visualise la source de la page), et s'il actualise, il recevra un avertissement de son navigateur (page expirée), ce qui pourrait être souhaitable.
Rob
0

Récemment, je travaillais sur un projet que j'utilise GET to Logout Ci-dessous, le code dans Nodejs Express et il fonctionne parfaitement bien

votre router.js

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

votre 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
la source
-2

Je ne vois pas comment la déconnexion (de-élévation des autorisations utilisateur) est une action destructrice. C'est parce que l'action "déconnexion" ne devrait être disponible que pour les utilisateurs déjà connectés, sinon elle serait obsolète.

Une chaîne générée aléatoirement contenue dans les cookies de votre navigateur représente tous votre session utilisateur. Il existe des tonnes de façons de le détruire si efficacement que la déconnexion n'est qu'un service rendu à votre visiteur.

jpluijmers
la source
2
wgeten mode araignée avec un cookie de session correct sur un wiki privé était une chose que j'avais en fait à faire une fois. Bien sûr, l'une des premières URL explorées a été /logout.
Helgi
5
Essayez d'aller sur SuperLogout.com pour voir à quel point les requêtes GET destructives sur les /logoutpages sont vraiment. Par exemple, vous devrez vous reconnecter à Gmail, vous reconnecter au chat, trouver votre place dans toutes les conversations Hangouts que vous avez faites défiler, etc. - et cela uniquement pour Google.com.
Dan Dascalescu