ChatGPT解决这个技术问题 Extra ChatGPT

Logout: GET or POST?

This question is not about when to use GET or POST in general; it is about which is the recommended one for handling logging out of a web application. I have found plenty of information on the differences between GET and POST in the general sense, but I did not find a definite answer for this particular scenario.

As a pragmatist, I'm inclined to use GET, because implementing it is way simpler than POST; just drop a simple link and you're done. This seems to be case with the vast majority of websites I can think of, at least from the top of my head. Even Stack Overflow handles logging out with GET.

The thing making me hesitate is the (albeit old) argument that some web accelerators/proxies pre-cache pages by going and retrieving every link they find in the page, so the user gets a faster response when she clicks on them. I'm not sure if this still applies, but if this was the case, then in theory a user with one of these accelerators would get kicked out of the application as soon as she logs in, because her accelerator would find and retrieve the logout link even if she never clicked on it.

Everything I have read so far suggest that POST should be used for "destructive actions", whereas actions that do not alter the internal state of the application -like querying and such- should be handled with GET. Based on this, the real question here is:

Is logging out of an application considered a destructive action/does it alter the internal state of the application?

Well, assuming you are visiting the site for the first time, and the logout link is not present, you would be logged out when you login. It would be fine after you logged in a second time, since the logout url is already cached. But one can assume any decent accelerator would be able to filter out most logout urls.
HyperCas, accelerators filtering out logout URLs was a theory I was considering and one of the reasons I decided to post the question. I feel a little reluctant to just trust the accelerator logic, and one day have a user with a crappy accelerator complain that she can't login. Do you know if they follow a standard, or if such standard exists?
Any Accelerator that automatically submitted a form (for example) would be malware IMO... it is totally illogical to think that an accelerator would submit a form automatically. Imagine you visit Google. How could it submit the search form? Nobody can account for Malware as it is too unpredictable and does not follow the rules.
@AlexW - I think you misunderstood my question. The accelerator scenario I proposed is to show a possible issue when using GET, not POST, so there would be no form to post, only plain links which accelerators would have no problems following.
I realise I'm years too late for this, but Alex, that's not what Daniel is asking about. He's saying that if a user clicks a logout link and an accelerator returns the cached logout page without it hitting the application, then the user would stay logged in. Nothing to do with malware, although FYI checking a User-Agent string wouldn't fix anything anyway.

D
David Murdoch

Use POST.

In 2010, using GET was probably an acceptable answer. But today (in 2013), browsers will pre-fetch pages they "think" you will visit next.

Here is one of the StackOverflow developers talking about this issue on twitter:

I'd like to thank my bank for making log off a GET request, and the Chrome team for handy URL prefetching.- Nick Craver (@Nick_Craver) January 29, 2013

fun fact: StackOverflow used to handle log-out via GET, but not anymore.


Thanks for this update, Dave. I didn't even notice SO switched their log out to POST, and I honestly had no clue Chrome comes with pre-fetching built in. Finally, the twit you quoted was could have never offered a better example to the problem I described in my my question and confirms my suspicions. I am up voting your answer and making it the accepted answer.
In my browser, Stackoverflow logout looks like
  • log out
  • which is a GET, not a POST
    @Mark0978, click the link.
    Interesting. That's probably one of my least favorite features, a logout that then asks me if I'm sure. Guess it keeps the prefetch from logging you out, but Amazon, Ebay, and Gmail all use GET for logout without that trick page in between what the user is told is logout and the actual logout event. I would imagine that in between page would lead to a lot of people mistakenly believing they were logged out. The problems with that on SO are minimal, no money involved, and 99% of everything is public anyway.
    @Red According to the HTTP/1.1 standard, this is the server's fault, not the browser's. GET is expected to have no side-effects on the server side. The standard even says "the user did not request the side-effects, so therefore cannot be held accountable for them".
    D
    Darrel Miller

    In REST there should be no session, therefore there is nothing to destroy. A REST client authenticates on every request. Logged in, or out, it's just an illusion.

    What you are really asking is should the browser continue sending the authentication information on every request.

    Arguably, if your application does create the illusion of being logged in, then you should be able to to "log out" using javascript. No round trip required.

    Fielding Dissertation - Section 5.1.3

    each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client


    I actually was not aware of this. Then I guess my app won't be very RESTful at all, as I'm using ASP.NET MVC with FormsAuthentication and it relies on sessions...
    but in practice the login info is kept in a cookie marked with the httponly attribute to prevent some xss risks, which means it can only be reset from the server (short of manually clearing the cookie)
    'Manual' as in the user goes to the Browser settings and chooses the 'Clear cookies' option. Hardly an acceptable way to 'log off' a web site.
    @Remus Ahhh, how the illustrious web browser makes writing web apps so painful.
    @DarrelMiller yes however not revoking a JWT on the server side is a security vulnerability. Even if the tokens are not stored on the server, they should be blacklisted when a user logs out/changes passwords/changes roles/quits/etc to prevent abuse (at least until they expire).
    r
    raveren

    One way GET could be abused here is that a person (competitor perhaps:) placed an image tag with src="<your logout link>" ANYWHERE on the internet, and if a user of your site stumbles upon that page, he will be unknowingly logged out.


    No, this is not right. A log out link will only work if the correct cookie data is sent, which it will not be from another domain. And even if the session id is stored in the url, that wouldn't work either as these change for every session.
    Wow, I never thought of that! So there, another reason not to use GET, and another reason I don't understand why everybody does it. Damn it, now I'm temped to include a stackoverflow.com/users/logout "image" too my post and see what happens :-D
    src= is a simple browser request, it does not come from server side, but from the client. It carries all cookies and comes from the user IP. That is why ad tracking pixels work. Only way to determine such exploit would be to check the referrer.
    SuperLogout.com does exactly that (load /logout URLs in hidden images), and it works.
    re:SuperLogout ... I do not know why I clicked that.
    m
    miorey

    Hello on my point of view, when you login you check username / password and if those are matching you create the login token.

    CREAT token => method POST

    When you are logging out you distroy the token so to me the most logical method should be a DELETE

    DELETE token => method DELETE


    Interesting angle.
    I use that method in my Spring Boot REST applications.
    Yes, but the URL for DELETE should identify the resource to delete so it can't be the same one as in the POST.
    @RonInbar agreed, if following REST 100%, then the POST to create a session should go to a [host name]/[user name]/session, as VinayC stated below. And DELETE should be like [host name]/[user name]/session/[session_id]. Yet using a DELETE to handle the deletion of session resources, even if getting the resource from a cookie instead of the URL, is better than using another verb to delete a resource (again, if trying to follow REST conventions).
    Conceptually this makes sense as long as the URL isn't /logout, since you're not deleting a logout (which doesn't make any sense), but deleting a session. So I guess login and logout would both hit the same endpoint, just with POST or DELETE to distinguish them
    V
    VinayC

    To be correct, GET/POST (or other verbs) are actions on some resource (addressed by URL) - so its generally about resource's state and not about application state as such. So in true spirits, you should have a URL such as [host name]\[user name]\session, then 'DELETE' would be the correct verb for log out action.

    Using [host name]\bla bla\logout as URL in not really an REST full way (IMO), so why debate about correct use of GET/POST on it?

    Of course, I also use GET to an logout url in my applications :-)


    In that case, I would then argue that having the [user name] part in the URL seems unnecessary, as users always logout from (i.e. DELETE) their own session; never other users' :-)
    Not really - we are saying that session is an resource and we want to delete it. So for uniformly addressing any session, you need to have user name as a part of URL. Your argument is as good as saying issuing PUT action on [photo gallary]\pictures means you are adding to your photos (available at [photo gallary]\[user name]\pictures). Different resources has to be addressed explicitly, there can't be any implicitness into it. The site may allow other users to add pictures to your gallery - it would be a part of access control just as you can have a super user who can kill anybody's sessions.
    Philosophically speaking, you could call sessions and photos 'resources', but realistically I wouldn't treat them the same. Session are always intrinsically restricted to the current user (hence the name Session) and, at least in ASP.NET, there is no way of accessing another user's sessions. Even the application developer has no direct way of enumerating all active sessions, or means to kill sessions individually. You could restart the application to kill all sessions (InProc), but I wouldn't call that access control. URLs aside, the question still remains: GET or POST?
    Resource, hence its address (URL) are important part of REST. So if you choose URL as I said, DELETE becomes the correct word - not GET or POST. Also, even if you are limiting yourself to ASP.NET, you can always have your custom state provider that can give you way to enumerate through sessions and kill other sessions if needed. For out of box in-proc sessions, some fiddling in global.asax should give you the functionality. Its really a question of whether such functionality would be needed or not. For infrequent needs, folks tend to re-start web site to kick people out of site.
    This make the most sense for me. Give the web api a session route and call DELETE on it. Be that ../session or ../session/current. Thankx @VinayC
    J
    Joel Etherton

    Logging out does nothing to the application itself. It changes the user's state in relation to the application. In this case, it appears your question is more based on how should the command be initiated from the user to begin this action. Since this is not a "destructive action", sure the session is abandoned or destroyed but neither your application or your data is altered, it is not infeasible to allow both methods to initiate a log out procedure. The post should be used by any user initiated actions (e.g. - user clicks "Log out"), while get could be reserved for application initiated log outs (e.g. - an exception detecting potential user intrusion forcibly redirects to the login page with a logout GET).


    This could conceivably depend on the application (some kind of "cascading delete" behavior), but you're right.
    @JoelEtherton Thank you Joel, I was reading down the answers wondering when I would get to the right one. :)
    It's confusing because logout changes state. POST is the verb for changing state. GET is for getting stateless data. It's confusing because we expect POST requests to have payloads. As noted below, DELETE would be most correct on a session object.
    @MichaelCole: I would agree with that representation of the difficulty between POST and GET. I wouldn't agree with the usage of the DELETE verb, though. DELETE is for handling a resource, and the session is not a resource in this sense. Consider, if you can DELETE it, then you should also be able to PUT it.
    @JoelEtherton, yes I agree about DELETE and PUT on sessions being a bit weird :-)
    R
    Richard H

    The scenario of pre-caching is an interesting one. But I'm guessing that if lots of sites inc SO do not worry about this then maybe you shouldn't either.

    Or perhaps the link could be implemented in javascript?

    Edit: As I understand it, technically a GET should be for read-only requests, that do not change application state. A POST should be for write/edit requests that change state. However other application issues might prefer GET over POST for some state-changing requests, and I do not think there is any problem with this.


    Thanks. The DB state wouldn't be changed, but the session state would. The only problem I see is the one I mentioned in the question, about users getting kicked out. Non-destructive but rather annoying. I usually go by the "if the big guys do it, then it must be OK" mantra too. I just wanted to know what opinion others have on this.
    R
    Rob

    Well if you let your web application abandon the session through a log out script, you usually don't need either. Normally there's a session variable that's unique for the session you want abandoned.


    Could you elaborate the "log out script"? I'm not sure if you are referring to setting a cookie expiration (which does not eliminate the need for a way of letting users manually logout.)
    A log out script would end the session of the user (actually: browser) calling it. In ASP.net, the session is a server side object which can be abandoned. PHP has a similar system. Because that browser calls the script that ends the session, it already knows which one to end, eliminating the need for POST or GET variables.
    Yes, I get you now. I already have the script in place, specifically FormsAuthentication.SignOut(), but my question is about how to invoke the script, as in GET or POST.
    Oh you have the url in a form? It doesn't matter if you're not passing any information to it. The worst thing that could happen is someone manually opening the script, logging themselves out. I wouldn't even make it a form field if not neccessary, a link to the script would work as well. If you DO send information to the script, I'd probably go for a POST, so as to not show any information to the user (unless they view the page source), and if they refresh they'll get a warning from their browser (page expired), which might be desirable.
    j
    jpluijmers

    I don't see how loging out (de-elevating user permissions) is a desctructive action. Thats because the "logout" action should be only available to users that are already logged in else it would be obsolete.

    A random generated string contained in your browser cookies is all representing your user session. There are tons of ways to destroy it so effectively logging out is merely a service to your visitor.


    wget in spider mode with a correct session cookie on an private wiki was a thing I actually had to do once. Of course, one of the first crawled URLs was /logout.
    Try going to SuperLogout.com to see how destructive GET requests to /logout pages really are. For example, you'll have to sign in into Gmail again, sign into chat again, find your place in any Hangouts conversations you had scrolled etc. - and this is only for Google.com.
    @DanDascalescu you should warn people that visiting this page will logout them immediately and there is no confirmation button! very angry emoji