Sair: GET ou POST?


435

Esta questão não é sobre quando usar GET ou POST em geral; é sobre qual é o recomendado para lidar com o logoff de um aplicativo da web. Encontrei muitas informações sobre as diferenças entre GET e POST no sentido geral, mas não encontrei uma resposta definitiva para esse cenário em particular.

Como pragmático, estou inclinado a usar o GET, porque implementá-lo é muito mais simples que o POST; basta soltar um link simples e pronto. Esse parece ser o caso da grande maioria dos sites em que consigo pensar, pelo menos do alto da minha cabeça. Até o Stack Overflow lida com o logout com GET.

O que me fez hesitar é o argumento (embora antigo) de que alguns aceleradores / proxies da Web pré-armazenam em cache as páginas acessando e recuperando todos os links encontrados na página, para que o usuário obtenha uma resposta mais rápida ao clicar nelas. Não tenho certeza se isso ainda se aplica, mas, se esse fosse o caso, em teoria, um usuário com um desses aceleradores seria expulso do aplicativo assim que efetuar o login, porque o acelerador encontraria e recuperaria o logout mesmo que ela nunca tenha clicado nele.

Tudo o que li até agora sugere que o POST deve ser usado para "ações destrutivas", enquanto as ações que não alteram o estado interno da consulta do aplicativo - como essas - devem ser tratadas com GET . Com base nisso, a verdadeira questão aqui é:

O logoff de um aplicativo é considerado uma ação destrutiva / altera o estado interno do aplicativo?


Bem, supondo que você esteja visitando o site pela primeira vez e o link de logout não estiver presente, você será desconectado ao fazer o login. Seria bom depois que você efetuou login pela segunda vez, já que o URL de logout já está armazenado em cache. Mas pode-se supor que qualquer acelerador decente seria capaz de filtrar a maioria dos URLs de logout.
— HyperCas 19/08

2
HyperCas, aceleradores que filtravam os URLs de logout era uma teoria que eu estava considerando e um dos motivos pelos quais decidi postar a pergunta. Sinto-me um pouco relutante em confiar apenas na lógica do acelerador e um dia um usuário com um acelerador de baixa qualidade reclama que não pode fazer login. Você sabe se eles seguem um padrão ou se esse padrão existe?
— Daniel Liuzzi

Qualquer acelerador que enviasse um formulário automaticamente (por exemplo) seria IMO de malware ... é totalmente ilógico pensar que um acelerador enviasse um formulário automaticamente. Imagine que você visita o Google. Como ele pôde enviar o formulário de pesquisa? Ninguém pode responder pelo malware, pois é imprevisível demais e não segue as regras.
— Alex19 de

3
@ AlexW - Acho que você não entendeu minha pergunta. O cenário do acelerador que propus é mostrar um possível problema ao usar o GET, não o POST, portanto não haveria forma de postagem, apenas links simples que os aceleradores não teriam problemas a seguir.
— precisa

1
Sei que estou anos atrasado para isso, mas Alex, não é sobre isso que Daniel está perguntando. Ele está dizendo que se um usuário clicar em um link de logoff e um acelerador retornar a página de logon em cache sem que ele atinja o aplicativo, o usuário permanecerá conectado. Nada a ver com malware, embora a verificação de uma sequência de caracteres User-Agent da FYI não conserte qualquer coisa de qualquer maneira.
— Rob Grant

Respostas:


476

Use POST.

Em 2010, o uso GETfoi provavelmente uma resposta aceitável. Mas hoje (em 2013), os navegadores buscarão previamente as páginas que eles "acham" que você visitará a seguir.

Aqui está um dos desenvolvedores do StackOverflow falando sobre esse problema no twitter:

Gostaria de agradecer ao meu banco por fazer o logoff de uma solicitação GET e à equipe do Chrome pela pré-busca prática de URLs. - Nick Craver ( @Nick_Craver ) 29 de janeiro de 2013

Curiosidade: StackOverflow costumava lidar com o logout via GET, mas não mais.


2
Obrigado por esta atualização, Dave. Eu nem percebi que a SO trocou o logout para o POST e, sinceramente, não fazia ideia de que o Chrome vem com a pré-busca incorporada. Finalmente, o twit que você citou nunca poderia oferecer um exemplo melhor para o problema que descrevi no meu minha pergunta e confirma minhas suspeitas. Estou votando sua resposta e fazendo dela a resposta aceita.
— Daniel Liuzzi

4
No meu navegador, o logout do Stackoverflow parece com <li> <a href="https://stackoverflow.com/users/logout"> logout </a> </li> que é um GET, não um POST #
— boatcoder

9
@ Mark0978, clique no link.
— David Murdoch

2
Interessante. Esse é provavelmente um dos meus recursos menos favoritos, um logout que me pergunta se tenho certeza. Acho que isso evita que a pré-busca faça o logout, mas Amazon, Ebay e Gmail usam GET para logout sem essa página de truque entre o que o usuário diz que é logout e o evento de logout real. Eu imaginaria que entre as páginas levaria muitas pessoas a acreditarem erroneamente que estavam desconectadas. Os problemas com isso no SO são mínimos, não há dinheiro envolvido e 99% de tudo é público de qualquer maneira.
— boatcoder

7
@Red De acordo com o padrão HTTP / 1.1, a culpa é do servidor, não do navegador. Espera-se que GET não tenha efeitos colaterais no lado do servidor. O padrão ainda diz "o usuário não solicitou os efeitos colaterais, portanto, não pode ser responsabilizado por eles".
— eyuelt

45

No REST, não deve haver sessão; portanto, não há nada para destruir. Um cliente REST é autenticado em cada solicitação. Entrar ou sair, é apenas uma ilusão.

O que você realmente está perguntando é se o navegador deve continuar enviando as informações de autenticação em cada solicitação.

Indiscutivelmente, se o seu aplicativo criar a ilusão de estar logado, você poderá "sair" usando javascript. Não é necessário ida e volta.


Dissertação de Campo - Seção 5.1.3

cada solicitação do cliente para o servidor deve conter todas as informações necessárias para entender a solicitação e não pode tirar proveito de nenhum contexto armazenado no servidor. O estado da sessão é, portanto, mantido inteiramente no cliente


1
Na verdade, eu não estava ciente disso. Então eu acho que meu aplicativo não será muito RESTful em tudo, como eu estou usando ASP.NET MVC com FormsAuthentication e se baseia em sessões ...
— Daniel Liuzzi

19
mas na prática a informação de login é mantida em um cookie marcado com o httponlyatributo para evitar alguns riscos XSS, o que significa que só pode ser reposto a partir do servidor (abreviação de limpar manualmente o cookie)
— Remus Rusanu

6
'Manual', como no usuário, acessa as configurações do navegador e escolhe a opção 'Limpar cookies'. Dificilmente é uma maneira aceitável de fazer logoff de um site.
— Remus Rusanu

1
@Remus Ahhh, como o ilustre navegador da web torna a escrita de aplicativos da web tão dolorosa.
— Darrel Miller

1
@DarrelMiller sim, no entanto, não revogar uma JWT no lado do servidor é uma vulnerabilidade de segurança. Mesmo se os tokens não estiverem armazenados no servidor, eles deverão estar na lista negra quando um usuário desconectar / alterar senhas / alterar funções / encerrar / etc para evitar abusos (pelo menos até que expirem).
— Java-addict301 15/05/19

39

Uma maneira de GETser abusada aqui é que uma pessoa (concorrente talvez :) colocou uma tag de imagem com src="<your logout link>"QUALQUER LUGAR na Internet e, se um usuário do seu site topar com essa página, ele será desconectado.


4
Não, isso não está certo. Um link de logoff funcionará apenas se os dados corretos do cookie forem enviados, o que não será de outro domínio. E mesmo se o ID da sessão estiver armazenado no URL, isso também não funcionaria, pois eles mudam para cada sessão.
— Richard H

4
Uau, eu nunca pensei nisso! Portanto, existe outro motivo para não usar GET, e outro motivo para não entender por que todo mundo faz isso. Droga, agora estou temped para incluir uma stackoverflow.com/users/logout "imagem" muito meu post e ver o que acontece :-D
— Daniel Liuzzi

24
src = é uma solicitação simples do navegador, não vem do lado do servidor, mas do cliente. Ele carrega todos os cookies e vem do IP do usuário. É por isso que os pixels de rastreamento de anúncios funcionam. A única maneira de determinar essa exploração seria verificar o referenciador.
— raveren

12
O SuperLogout.com faz exatamente isso (carrega /logoutURLs em imagens ocultas) e funciona.
— Dan Dascalescu 28/01

9
re: SuperLogout ... Não sei por que cliquei nisso.
— MI Wright

21

Para ser correto, GET / POST (ou outros verbos) são ações em algum recurso (endereçado por URL) - portanto, geralmente trata-se do estado do recurso e não do estado do aplicativo como tal. Portanto, com espírito de verdade, você deve ter um URL como [host name]\[user name]\session, 'DELETE' seria o verbo correto para a ação de logout.

Usar [host name]\bla bla\logoutcomo URL não é realmente um caminho completo REST (IMO), então por que debater sobre o uso correto de GET / POST nele?

Obviamente, eu também uso GET em um URL de logout em meus aplicativos :-)


2
Nesse caso, eu argumentaria que ter o [nome do usuário] parte da URL parece desnecessário, pois os usuários sempre desconectam (ex: DELETE) de sua própria sessão; nunca outros utilizadores :-)
— Daniel Liuzzi

1
Na verdade, não - estamos dizendo que a sessão é um recurso e queremos excluí-lo. Portanto, para endereçar uniformemente qualquer sessão, você precisa ter o nome de usuário como parte da URL. Seu argumento é tão bom quanto dizer que emitir ação PUT em [galeria de fotos] \ fotos significa que você está adicionando às suas fotos (disponível em [galeria de fotos] \ [nome do usuário] \ fotos). Recursos diferentes precisam ser abordados explicitamente, não pode haver nenhuma implicação nele. O site pode permitir que outros usuários adicionem fotos à sua galeria - isso faria parte do controle de acesso, assim como você pode ter um superusuário que pode matar as sessões de qualquer pessoa.
— VinayC

1
Filosoficamente, você poderia chamar sessões e fotos de 'recursos', mas, realisticamente, eu não os trataria da mesma maneira. A sessão é sempre intrinsecamente restrita ao usuário atual (daí o nome Session) e, pelo menos no ASP.NET, não há como acessar as sessões de outro usuário. Mesmo o desenvolvedor do aplicativo não possui uma maneira direta de enumerar todas as sessões ativas ou meios de eliminar as sessões individualmente. Você pode reiniciar o aplicativo para eliminar todas as sessões (InProc), mas eu não chamaria esse controle de acesso. URLs à parte, a questão ainda permanece: GET ou POST?
— Daniel Liuzzi

Recurso, portanto, seu endereço (URL) é parte importante do REST. Portanto, se você escolher o URL como eu disse, DELETE se tornará a palavra correta - não GET ou POST. Além disso, mesmo se você estiver se limitando ao ASP.NET, sempre poderá ter seu provedor de estado personalizado, que pode lhe permitir enumerar as sessões e interromper outras, se necessário. Para sessões in-proc prontas para o uso, algumas brincadeiras no global.asax devem fornecer a funcionalidade. É realmente uma questão de saber se essa funcionalidade seria necessária ou não. Para necessidades pouco frequentes, as pessoas tendem a reiniciar o site para expulsar as pessoas.
— precisa saber é o seguinte

Isso faz mais sentido para mim. Dê à API da Web uma rota de sessão e chame DELETE nela. Seja ../session ou ../session/current. Thankx @VinayC
— Simon Hooper

16

O logout não faz nada para o próprio aplicativo. Ele altera o estado do usuário em relação ao aplicativo. Nesse caso, parece que sua pergunta é mais baseada em como o comando deve ser iniciado pelo usuário para iniciar esta ação. Como essa não é uma "ação destrutiva", verifique se a sessão foi abandonada ou destruída, mas que nem seu aplicativo nem seus dados foram alterados, não é inviável permitir que ambos os métodos iniciem um procedimento de logoff. A postagem deve ser usada por qualquer ação iniciada pelo usuário (por exemplo - o usuário clica em "Logout"), enquanto o get pode ser reservado para logouts iniciados pelo aplicativo (por exemplo - uma exceção que detecta uma possível invasão do usuário forçosamente redireciona para a página de login com um logout GET )


Interessante; Eu nunca pensei nisso dessa maneira. +1.
— Stragner

É possível que isso dependa do aplicativo (algum tipo de comportamento de "exclusão em cascata"), mas você está certo.
— Andres Jaan Tack

@ JoelEtherton Obrigado Joel, eu estava lendo as respostas, imaginando quando chegaria à correta. :)
— Kirill Fuchs

4
É confuso porque o logout muda de estado. POST é o verbo para mudar de estado. GET é para obter dados sem estado. É confuso porque esperamos que as solicitações POST tenham cargas úteis. Conforme observado abaixo, DELETE estaria mais correto em um objeto de sessão.
— Michael Cole

1
@ MichaelCole: Eu concordo com essa representação da dificuldade entre o POST e o GET. Eu não concordaria com o uso do verbo DELETE. DELETE é para manipular um recurso e a sessão não é um recurso nesse sentido. Considere, se você puder EXCLUIR, também poderá COLOCÁ-lo.
— Joel Etherton

16

Olá, do meu ponto de vista, ao fazer login, verifique o nome de usuário / senha e, se houver algum, crie o token de login.

Token CREAT => método POST

Quando você está desconectando, distribui o token, portanto, para mim, o método mais lógico deve ser um DELETE

Token DELETE => método DELETE


4
Ângulo interessante.
— Drumbeg

1
Eu uso esse método em meus aplicativos Spring Boot REST.
— Please_Dont_Bully_Me_SO_Lords

1
semanticamente correto. Concordo ...
— DAG

1

O cenário de pré-cache é interessante. Mas suponho que, se muitos sites inc SO, não se preocupem com isso, talvez você também não deva.

Ou talvez o link possa ser implementado em javascript?

Edit: Pelo que entendi, tecnicamente um GET deve ser para solicitações somente leitura, que não alteram o estado do aplicativo. Um POST deve ser para solicitações de gravação / edição que mudam de estado. No entanto, outros problemas de aplicativos podem preferir GET sobre POST para algumas solicitações de alteração de estado, e eu não acho que haja algum problema com isso.


Obrigado. O estado do banco de dados não seria alterado, mas o estado da sessão seria. O único problema que vejo é o que mencionei na pergunta, sobre os usuários serem expulsos. Não destrutivo, mas bastante irritante. Eu costumo seguir o mantra "se os grandes fazem isso, então deve estar tudo bem" também. Eu só queria saber que opinião os outros têm sobre isso.
— Daniel Liuzzi

0

Bem, se você deixar seu aplicativo Web abandonar a sessão por meio de um script de logoff, geralmente não será necessário. Normalmente, há uma variável de sessão exclusiva para a sessão que você deseja abandonar.


Você poderia elaborar o "script de logoff"? Eu não tenho certeza se você está se referindo a definir uma expiração do cookie (o que não elimina a necessidade de uma maneira de deixar os usuários manualmente o logout.)
— Daniel Liuzzi

Um script de logout encerraria a sessão do usuário (na verdade: navegador) que está chamando. No ASP.net, a sessão é um objeto do lado do servidor que pode ser abandonado. O PHP tem um sistema semelhante. Como esse navegador chama o script que encerra a sessão, ele já sabe qual final, eliminando a necessidade de variáveis ​​POST ou GET.
— Rob

1
Sim, eu te pego agora. Eu já tenho o script no lugar, especificamente FormsAuthentication.SignOut (), mas minha pergunta é sobre como chamar o script, como em GET ou POST.
— Daniel Liuzzi

Oh você tem o URL em um formulário? Não importa se você não está passando nenhuma informação para ele. A pior coisa que poderia acontecer é alguém abrir o script manualmente, se desconectando. Eu nem faria dele um campo de formulário, se não necessário, um link para o script também funcionaria. Se você enviar informações para o script, eu provavelmente faria um POST, para não mostrar nenhuma informação ao usuário (a menos que ele veja a fonte da página) e, se atualizar, receberá um aviso do navegador (página expirada), o que pode ser desejável.
— Rob

0

Recentemente, eu estava trabalhando em um projeto que uso GET para sair. Abaixo está o código no Nodejs Express e funciona perfeitamente bem

seu router.js

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

seu 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

Não vejo como fazer logoff (removendo as permissões de usuário) é uma ação destrutiva. Isso ocorre porque a ação "logout" deve estar disponível apenas para usuários que já estão conectados, caso contrário, seria obsoleta.

Uma sequência gerada aleatoriamente contida nos cookies do navegador está representando a sua sessão do usuário. Existem várias maneiras de destruí-lo de forma tão eficaz. O logout é apenas um serviço para o visitante.


2
wgetno modo spider, com um cookie de sessão correto em um wiki privado, era algo que eu realmente tive que fazer uma vez. Obviamente, um dos primeiros URLs rastreados foi /logout.
— Helgi

5
Tente acessar SuperLogout.com para ver como as solicitações GET destrutivas para as /logoutpáginas realmente são. Por exemplo, você precisará fazer login no Gmail novamente, entrar no bate-papo novamente, encontrar seu lugar nas conversas do Hangouts que rolou etc. - e isso é apenas para Google.com.
— Dan Dascalescu 29/01
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.