Se os aplicativos REST devem ser sem estado, como você gerencia as sessões?

536

Estou precisando de alguns esclarecimentos. Eu tenho lido sobre o REST e construindo aplicativos RESTful. De acordo com a wikipedia, o próprio REST é definido como Representational State Transfer . Portanto, não entendo todo esse livro apático sem estado que todo mundo continua vomitando.

Da wikipedia:

A qualquer momento específico, um cliente pode estar em transição entre os estados do aplicativo ou "em repouso". Um cliente em um estado de repouso pode interagir com seu usuário, mas não cria carga e não consome armazenamento por cliente no conjunto de servidores ou na rede.

Eles estão dizendo que não usam armazenamento de dados no nível da sessão / aplicativo ???

Entendo que um dos objetivos do REST é tornar o acesso ao URI consistente e disponível, por exemplo, em vez de ocultar solicitações de paginação nas postagens, tornando o número da página de uma solicitação parte do GET URI. Faz sentido para mim. Mas parece que está exagerando dizendo que nenhum dado por cliente (sessão) deve ser armazenado no servidor.

E se eu tivesse uma fila de mensagens e meu usuário quisesse ler as mensagens, mas, ao lê-las, quisesse bloquear certas mensagens de remetentes que chegassem durante a sessão? Não faria sentido armazenar isso em um local no lado do servidor e fazer com que o servidor envie apenas mensagens (ou IDs) que não foram bloqueadas pelo usuário?

Preciso realmente enviar a lista inteira de remetentes para bloquear cada vez que solicitar a nova lista de mensagens? A lista de mensagens pertinente para mim nem deveria ser um recurso disponível ao público em primeiro lugar.

Mais uma vez, apenas tentando entender isso. Alguém por favor, esclareça.


Atualizar:

Eu encontrei uma pergunta de estouro de pilha que tem uma resposta que não me leva a todo o caminho: Como gerenciar o estado no REST, que diz que o estado do cliente que é importante deve ser transferido a cada solicitação ... Ugg .. parece muita sobrecarga ... Isso está certo ??

Zak
fonte
2
@ S.Lott: Eu não acho que é intencionalmente enganador. Eu acho que é um mal-entendido por causa de terminologia confusa.
APENAS MINHA OPINIÃO correta
2
@ APENAS MINHA OPINIÃO correta: palpite interessante. Eu mesmo não podia acreditar nisso, pois é óbvio que "sem estado" significa que o próprio protocolo REST é sem estado; que não diz nada sobre o estado do aplicativo subjacente e atualiza-o com solicitações PUT, POST e DELETE.
S.Lott
@ S.Lott: O protocolo HTTP em si é sem estado. Pelo que discutimos abaixo, o REST é um ponto de vista de como criar seu aplicativo sem que o servidor da web lide com o estado da sessão (em oposição a outros tipos de estado em coisas como o DB). Eu nem pensei que o REST era um protocolo, mas uma visão de como usar o protocolo HTTP. Eu pensei que vocês esclareceram que era sobre como construir seu aplicativo em escala, fazendo com que o lado do cliente armazene todos os dados de sessão específicos do cliente e tornando os acessos ao URI o mais idempotentes possível, exceto onde não deveriam estar. Talvez não ... :(
Zak
1
"Talvez não .." O que isso significa? Você tem uma nova pergunta? Sinta-se livre para procurar por isso. Se não existir aqui, pergunte.
S.Lott
Alguém já leu o ReST in Practice de Webber, Parastatidis e Robinson (ou viu o exemplo do seu restbucks)? As respostas abaixo fazem sentido, mas certamente os pedidos de café no exemplo do restbucks são válidos para um cliente? O número de pedidos é escalonado com o número de clientes. Onde está a linha entre o estado do cliente e um recurso?
Rikki

Respostas:

340

Apatridia significa que toda solicitação HTTP acontece em isolamento completo. Quando o cliente faz uma solicitação HTTP, inclui todas as informações necessárias para o servidor atender a essa solicitação. O servidor nunca conta com informações de solicitações anteriores. Se essas informações fossem importantes, o cliente teria que enviá-las novamente em uma solicitação subsequente. A apatridia também traz novos recursos. É mais fácil distribuir um aplicativo sem estado entre servidores com balanceamento de carga. Um aplicativo sem estado também é fácil de armazenar em cache.

Na verdade, existem dois tipos de estado. Estado do Aplicativo que fica no cliente e Estado do Recurso que fica no servidor.

Um serviço da web precisa se preocupar apenas com o estado do seu aplicativo quando você está realmente fazendo uma solicitação. O resto do tempo, nem sabe que você existe. Isso significa que sempre que um cliente faz uma solicitação, ele deve incluir todos os estados do aplicativo que o servidor precisará para processá-la.

O estado do recurso é o mesmo para todos os clientes e seu local apropriado está no servidor. Ao carregar uma imagem em um servidor, você cria um novo recurso: a nova imagem possui seu próprio URI e pode ser o destino de solicitações futuras. Você pode buscar, modificar e excluir este recurso por meio de HTTP.

Espero que isso ajude a diferenciar o que significa apatridia e vários estados.

Srikar Doddi
fonte
4
Isso significa que toda vez que uma solicitação é enviada, o cliente deve enviar seu usuário / senha para autenticação? Porque eu acho que armazenar uma sessão, mesmo que ela esteja em um db no-sql compartilhado entre todos os servidores, não é sem estado ou é?
Carlos Navarro Astiasarán
1
@ CarlosNavarroAstiasarán existem várias técnicas para lidar com a autenticação sem estado. Google JWT, por exemplo.
geoidesic
1
@geoidesic: "Como os tokens da web JSON são sem estado, não há como invalidá-los sem armazenar o estado do servidor, derrotando a vantagem dos tokens sem estado." Wikipedia
ulatekh
@ulatekh Essa é uma deturpação grosseira do que você pode fazer com os tokens. É muito simples armazenar um ID aprovado junto com o token e aceitar apenas tokens que tenham um ID aprovado como reivindicação. Stateless não significa que você não pode algo em um banco de dados. Essencialmente, você armazena um ID no banco de dados que deve corresponder ao mesmo ID no token. Para revogar o token, você remove o ID do banco de dados. Nenhum estado é lembrado no próprio serviço. Ou melhor ainda, você armazena a chave de assinatura com o usuário no banco de dados e revoga a chave.
Andrew T Finnell
@AndrewTFinnell: Se você precisar armazenar o ID aprovado no servidor, ele deverá ser armazenado em todos os servidores em potencial que possam processar o logon REST, o que poderá envolver muitos estados do servidor em uma arquitetura de servidor da Web paralela.
ulatekh
491

A explicação fundamental é:

Nenhum estado da sessão do cliente no servidor.

Por sem estado, significa que o servidor não armazena nenhum estado sobre a sessão do cliente no lado do servidor.

A sessão do cliente é armazenada no cliente. O servidor é sem estado, significa que todo servidor pode atender a qualquer cliente a qualquer momento, não há afinidade de sessão ou sessões permanentes . As informações relevantes da sessão são armazenadas no cliente e transmitidas ao servidor conforme necessário.

Isso não impede que outros serviços com os quais o servidor da Web converse mantenham o estado sobre objetos de negócios, como carrinhos de compras, mas não sobre o estado atual do aplicativo / sessão do cliente.

O estado do aplicativo do cliente nunca deve ser armazenado no servidor, mas passado do cliente para todos os locais que precisam dele.

É daí que o ST no REST vem, Transferência de Estado . Você transfere o estado ao redor, em vez de o servidor armazená-lo. Essa é a única maneira de expandir para milhões de usuários simultâneos. Se não por outro motivo, porque milhões de sessões são milhões de sessões.

A carga do gerenciamento de sessões é amortizada em todos os clientes, os clientes armazenam seu estado de sessão e os servidores podem atender a muitas ordens de magnitude ou mais clientes de maneira apátrida.

Mesmo para um serviço que você acha que precisará apenas nos 10 dos milhares de usuários simultâneos, você ainda deve tornar seu serviço sem estado. Dezenas de milhares ainda são dezenas de milhares e haverá tempo e espaço associados a ele.

Sem estado de estado é como o protocolo HTTP e a Web em geral foram projetados para operar e é uma implementação geral mais simples e você tem um único caminho de código em vez de um monte de lógica do lado do servidor para manter vários estados de sessão.

Existem alguns princípios de implementação muito básicos:

Estes são princípios, não implementações. A forma como você cumpre esses princípios pode variar.

Em resumo, os cinco princípios principais são:

  1. Dê a cada "coisa" um ID
  2. Vincular as coisas
  3. Use métodos padrão
  4. Recursos com várias representações
  5. Comunique-se apátrida

Não há nada sobre autenticação ou autorização na dissertação REST .

Porque não há nada diferente de autenticar uma solicitação que é RESTful de uma que não é. A autenticação é irrelevante para a discussão RESTful.

Explicar como criar um aplicativo sem estado para seus requisitos específicos é muito amplo para o StackOverflow.

A implementação da autenticação e autorização no que diz respeito ao REST é ainda mais abrangente e várias abordagens para implementações são explicadas em detalhes na Internet em geral.

Os comentários que solicitam ajuda / informações sobre isso serão / devem ser sinalizados como Não é mais necessário .


fonte
22
Parece uma afirmação bastante ousada de que é a única maneira de escalar para milhões de usuários. Por que as sessões do servidor não podem ser apenas outro serviço?
Zak
27
@Zak: Porque milhões de sessões são milhões de sessões. O objetivo é evitar a sobrecarga de todo esse gerenciamento de sessões.
S.Lott
91
não é ousadia, é experiência
21
Nada na minha resposta implica uma solução baseada no acesso ao banco de dados em todas as solicitações; se você acha que sim, é uma falha da sua parte entender a autenticação e a autorização nessa escala. A autenticação pode estar implícita no estado. Você acha que o facebook faz um "acesso ao banco de dados" em cada solicitação de sua API REST? Ou o Google para esse assunto? dica: no
6
Portanto, se eu armazenar o estado do usuário em um cache distribuído, por exemplo, memcache, e agora todo o meu servidor da Web não precisará armazenar nenhum estado, mas obter o estado do memcache, posso considerar esse aplicativo sem estado?
Jaskey
76

Eles estão dizendo que não usam armazenamento de dados no nível da sessão / aplicativo ???

Não. Eles não estão dizendo isso de uma maneira trivial.

Eles estão dizendo que não definem uma "sessão". Não faça login. Não efetue logout. Forneça credenciais com a solicitação. Cada solicitação fica sozinha.

Você ainda tem repositórios de dados. Você ainda tem autenticação e autorização. Você simplesmente não perde tempo estabelecendo sessões e mantendo o estado da sessão.

O ponto é que cada solicitação (a) fica completamente sozinha e (b) pode ser trivialmente gerida em um farm de servidores paralelos gigante sem nenhum trabalho real. O Apache ou o Squid podem transmitir solicitações RESTful cegamente e com êxito.

E se eu tivesse uma fila de mensagens e meu usuário quisesse ler as mensagens, mas, ao lê-las, quisesse bloquear certas mensagens de remetentes que chegassem durante a sessão?

Se o usuário desejar um filtro, simplesmente forneça o filtro em cada solicitação.

Não faria sentido ... o servidor enviar apenas mensagens (ou IDs) que não foram bloqueadas pelo usuário?

Sim. Forneça o filtro na solicitação de URI RESTful.

Preciso realmente enviar a lista inteira de remetentes para bloquear cada vez que solicitar a nova lista de mensagens?

Sim. Qual o tamanho dessa "lista de remetentes de mensagens a serem bloqueadas"? Uma pequena lista de PK's?

Uma solicitação GET pode ser muito grande. Se necessário, você pode tentar uma solicitação POST, mesmo que pareça um tipo de consulta.

S.Lott
fonte
28
"Não faça login. Não efetue logout. Forneça credenciais com a solicitação." Eu sempre vejo respostas como essa em perguntas sobre como permanecer apátrida em uma API REST sem detalhes sobre onde / como deve-se armazenar essas credenciais no cliente. Certamente não devemos armazenar nome de usuário e senha no armazenamento local!
BeniRose
2
@BeniRose não podemos armazenar um token no armazenamento local e usá-lo em solicitações que identificarão exclusivamente o usuário?
Nikhil Sahu
1
Localstorage tem muitas preocupações de segurança, pelo que entendi. Mas também há um monte de outras preocupações com sessões do lado do cliente, como invalidar os tokens, registrando um fora do usuário, etc.
BeniRose
3
você usa o JWT que possui uma assinatura, a verificação da assinatura é rápida para que você possa verificar a validade desse estado.
Archimedes Trajano
36

Você está absolutamente certo, oferecer suporte a interações completamente sem estado de estado com o servidor gera um ônus adicional para o cliente. No entanto, se você considerar dimensionar um aplicativo, o poder de computação dos clientes é diretamente proporcional ao número de clientes. Portanto, escalar para um grande número de clientes é muito mais viável.

Assim que você coloca uma pequena responsabilidade no servidor para gerenciar algumas informações relacionadas às interações de um cliente específico, esse ônus pode aumentar rapidamente para consumir o servidor.

É uma troca.

Darrel Miller
fonte
32

Visualização histórica do gerenciamento de estado do aplicativo do usuário

As sessões no sentido tradicional mantêm o estado do usuário no aplicativo dentro do servidor. Pode ser a página atual em um fluxo ou o que foi inserido anteriormente, mas ainda não persistiu no banco de dados principal.

O motivo dessa necessidade foi a falta de padrões no lado do cliente para manter efetivamente o estado sem criar aplicativos ou plug-ins específicos do cliente (ou seja, específicos do navegador).

Com o passar do tempo, a solicitação de cabeçalho HTML5 e XML padronizou a noção de armazenamento de dados complexos, incluindo o estado do aplicativo de maneira padrão no lado do cliente (por exemplo, navegador), sem recorrer à alternância entre o servidor.

Uso geral de serviços REST

Os serviços REST são geralmente chamados quando há uma transação que precisa ser executada ou se precisa recuperar dados.

Os serviços REST devem ser chamados pelo aplicativo do lado do cliente e não diretamente pelo usuário final.

Autenticando

Para qualquer solicitação ao servidor, parte da solicitação deve conter o token de autorização. Como é implementado é específico da aplicação, mas em geral é um BASICouCERTIFICATE forma de autenticação.

A autenticação baseada em formulário não é usada pelos serviços REST. No entanto, conforme observado acima, os serviços REST não devem ser chamados pelo usuário, mas pelo aplicativo. O aplicativo precisa gerenciar a obtenção do token de autenticação. No meu caso, usei cookies com JASPIC com OAuth 2.0 para conectar-me ao Google para autenticação e autenticação HTTP simples para testes automatizados. Também usei autenticação de cabeçalho HTTP via JASPIC para testes locais (embora a mesma abordagem possa ser realizada no SiteMinder)

De acordo com esses exemplos, a autenticação é gerenciada no lado do cliente (embora o SiteMinder ou o Google armazenem a sessão de autenticação), não há nada que possa ser feito sobre esse estado, mas não faz parte do aplicativo de serviço REST.

Solicitações de recuperação

Solicitações de recuperação no REST são GEToperações nas quais um recurso específico é solicitado e é armazenável em cache. Não há necessidade de sessões do servidor porque a solicitação tem tudo o que seria necessário para recuperar os dados: autenticação e o URI.

Scripts de transação

Conforme observado acima, o próprio aplicativo do lado do cliente chama os serviços REST junto com a autenticação que ele gerencia no lado do cliente.

O que isso significa para os serviços REST [se feito corretamente] é levar uma única solicitação ao servidor REST conterá tudo o que é necessário para uma operação de usuário único que faz tudo o que é necessário em uma única transação, um Script de Transação é o padrão é chamado.

Isso é feito através de uma POSTsolicitação normalmente, mas outras PUTtambém podem ser usadas.

Muitos exemplos inventados de REST (eu mesmo fiz isso) tentaram seguir o que foi definido no protocolo HTTP, depois de passar por isso, decidi ser mais pragmático e o deixei apenas para GET e POST . O POSTmétodo nem precisa implementar o padrão POST-REDIRECT-GET.

Independentemente disso, como observei acima, o aplicativo do lado do cliente será POSTo responsável pela chamada do serviço e somente chamará a solicitação com todos os dados quando necessário (nem sempre). Isso evita solicitações constantes para o servidor.

Polling

Embora o REST também possa ser usado para pesquisas, não o recomendo, a menos que você precise usá-lo devido à compatibilidade do navegador. Para isso, eu usaria WebSockets para os quais também havia criado um contrato de API . Outra alternativa para navegadores mais antigos é o CometD.

Archimedes Trajano
fonte
27

O REST é muito abstrato. Ajuda a ter alguns exemplos bons, simples e do mundo real.

Tomemos, por exemplo, todos os principais aplicativos de mídia social - Tumblr, Instagram, Facebook e Twitter. Todos eles têm uma visão de rolagem permanente, onde quanto mais você rola para baixo, mais conteúdo você vê, mais e mais no tempo. No entanto, todos experimentamos aquele momento em que você perde para onde foi rolado e o aplicativo redefine você de volta ao topo. Por exemplo, se você sair do aplicativo, ao reabri-lo, estará novamente no topo.

O motivo é que o servidor não armazenou o estado da sua sessão. Infelizmente, sua posição de rolagem acabou de ser armazenada na RAM do cliente.

Felizmente, você não precisa fazer login novamente ao se reconectar, mas isso ocorre apenas porque o certificado de login armazenado do lado do cliente também não expirou. Exclua e reinstale o aplicativo, e você precisará fazer login novamente, porque o servidor não associou seu endereço IP à sua sessão.

Você não tem uma sessão de logon no servidor, porque eles seguem o REST.


Agora, os exemplos acima não envolvem um navegador da Web, mas, no back-end, os aplicativos estão se comunicando via HTTPS com seus servidores host. O que quero dizer é que o REST não precisa envolver cookies e navegadores etc. Existem vários meios de armazenar o estado da sessão no lado do cliente.

Mas vamos falar sobre navegadores da Web por um segundo, porque isso traz outra grande vantagem do REST da qual ninguém está falando aqui.

Se o servidor tentou armazenar o estado da sessão, como ele deve identificar cada cliente individual?

Não foi possível usar o endereço IP, porque muitas pessoas poderiam estar usando o mesmo endereço em um roteador compartilhado. Então como?

Ele não pode usar o endereço MAC por vários motivos, pelo menos porque você pode estar conectado a várias contas diferentes do Facebook simultaneamente em diferentes navegadores e no aplicativo. Um navegador pode facilmente fingir ser outro, e os endereços MAC são igualmente fáceis de falsificar.

Se o servidor precisar armazenar algum estado do lado do cliente para identificá-lo, precisará armazená-lo na RAM por mais tempo do que o tempo necessário para processar suas solicitações, ou então, deverá armazenar em cache esses dados. Os servidores possuem quantidades limitadas de RAM e cache, sem mencionar a velocidade do processador. O estado do lado do servidor é adicionado aos três, exponencialmente. Além disso, se o servidor armazenar qualquer estado sobre suas sessões, será necessário armazená-lo separadamente para cada navegador e aplicativo com o qual você está conectado no momento e também para cada dispositivo diferente usado.


Então ... espero que você veja agora porque o REST é tão importante para a escalabilidade. Espero que você possa começar a ver por que o estado da sessão no servidor é a escalabilidade do servidor, o que são as bigornas soldadas para a aceleração do carro.


As pessoas ficam confusas pensando que "estado" se refere a informações armazenadas em um banco de dados. Não, refere-se a qualquer informação que precise estar na RAM do servidor quando você a estiver usando.

CommaToast
fonte
13

Vejo que a questão básica aqui é misturar Sessão com Estado . E enquanto o REST especifica que você NÃO deve armazenar o Estado no servidor, nada impede que você armazene uma Sessão do usuário .

Gerenciar o estado no servidor significa que o servidor sabe exatamente o que o cliente está fazendo (em que página está visualizando em qual seção do aplicativo). E é isso que você não precisa fazer.

Concordo com as outras pessoas dizendo que você deve manter o armazenamento da sessão em um tamanho mínimo; e, embora isso seja bom senso, na verdade também depende da aplicação. Portanto, em resumo, você ainda pode manter uma sessão com dados em cache para lidar com as solicitações com menos carga no servidor e gerenciar a autenticação fornecendo um token de autenticação / acesso temporário para o cliente usar. Sempre que a sessão / token expirar, gere um novo e peça ao cliente para usá-lo.

Alguém pode argumentar que o cliente deve gerar melhor o token. Eu digo que funciona nos dois sentidos, e dependeria do aplicativo, e quem trabalhará com a API.

Manter alguns dados confidenciais da sessão no servidor também deve ser o caminho certo. Você não pode confiar no cliente para manter o carrinho de compras que (por exemplo) contém um campo chamado "isFreeGift". Essas informações devem ser mantidas no servidor.

O link do vídeo fornecido por Santanu Dey em sua resposta é útil. Assista se você não tiver.

Apenas uma observação: Parece que todas as respostas já dadas parecem desconsiderar o fato de que algumas operações podem causar uma carga pesada no servidor. Isso é relevante em termos de consumo de energia, consumo de hardware e custo (para servidores alugados pelo ciclo da CPU). Um bom desenvolvedor não deve ter preguiça de otimizar seu aplicativo, mesmo que a operação possa ser feita muito rapidamente em uma CPU moderna em algum servidor alugado pelo qual eles não pagam sua conta de energia e manutenção.

Embora a pergunta tenha alguns anos, espero que minha resposta ainda seja útil.

Sam Sirry
fonte
4
Eu geralmente concordo com esse sentimento, mas houve uma tendência recente de afirmar que mesmo um identificador de sessão não deve ser armazenado no servidor. Eu ainda tenho que descobrir o que a solução alternativa é, JWT é bem elogiado, mas vem com um punhado de truques: cryto.net/~joepie91/blog/2016/06/19/...
BeniRose
11

Sem estado significa que o estado do serviço não persiste entre solicitações e respostas subseqüentes. Cada solicitação possui suas próprias credenciais de usuário e é autenticada individualmente. Porém, em stateful, cada solicitação é conhecida de qualquer solicitação anterior. Todas as solicitações com estado são orientadas à sessão, ou seja, cada solicitação precisa conhecer e reter as alterações feitas nas solicitações anteriores.

O aplicativo bancário é um exemplo de aplicativo com estado. Onde o usuário primeiro efetua login, efetue a transação e efetue logout. Se após o logout, o usuário tentar fazer a transação, ele não poderá fazer isso.

Sim, o protocolo http é essencialmente um protocolo sem estado, mas para torná-lo com estado, criamos cookies HTTP. Então, é SOAP por padrão. Mas pode ser feito da mesma forma, depende da estrutura que você está usando.

O HTTP é sem estado, mas ainda podemos manter a sessão em nosso aplicativo java usando diferentes mecanismos de rastreamento de sessão.

Sim, também podemos manter a sessão no serviço da web, seja REST ou SOAP. Ele pode ser implementado usando qualquer biblioteca de terceiros ou você pode implementar por conta própria.

Retirado de http://gopaldas.org/webservices/soap/webservice-is-stateful-or-stateless-rest-soap

Ata ul Mustafa
fonte
11

Não tem colher.

Não pense em apatridia como "enviar todas as suas coisas para o servidor várias vezes". De jeito nenhum. Sempre haverá estado - o banco de dados em si é um tipo de estado, afinal, você é um usuário registrado, portanto, qualquer conjunto de informações do lado do cliente não será válido sem o lado do servidor. Tecnicamente, você nunca é verdadeiramente apátrida.

Uma palavra no debate de login sempre

O que significa mesmo não manter uma sessão e fazer login sempre? Alguns significam "enviar a senha de cada vez", isso é estúpido. Alguns dizem "nah, claro que não, envie um token " - e eis que a sessão do PHP está fazendo quase exatamente isso. Ele envia um ID de sessão que é um tipo de token e ajuda você a acessar suas coisas pessoais sem reenviar o u / pw todas as vezes. Também é bastante confiável e bem testado. E sim, conveniente, que pode se transformar em uma desvantagem, veja o próximo parágrafo.

Reduzir pegada

Em vez disso, o que você deve fazer e o que faz realmente sentido é reduzir ao mínimo o espaço ocupado pelo servidor da web. Idiomas como o PHP tornam muito fácil colocar tudo no armazenamento da sessão - mas as sessões têm um preço. Se você possui vários servidores da Web, eles precisam compartilhar informações da sessão, porque também compartilham a carga - qualquer um deles pode precisar atender à próxima solicitação.

Um armazenamento compartilhado é uma obrigação. O servidor precisa saber pelo menos se alguém está logado ou não. (E se você incomodar o banco de dados toda vez que precisar decidir isso, estará praticamente condenado.) Os armazenamentos compartilhados precisam ser muito mais rápidos que o banco de dados. Isso traz a tentação: ok, eu tenho um armazenamento muito rápido, por que não fazer tudo lá? - e é aí que as coisas ficam desagradáveis ​​do outro lado.

Então você está dizendo, mantenha o armazenamento da sessão no mínimo?

Novamente, a decisão é sua. Você pode armazenar coisas por motivos de desempenho (o banco de dados quase sempre é mais lento que o Redis), você pode armazenar informações de forma redundante, implementar seu próprio cache, o que for - lembre-se de que os servidores da Web terão uma carga maior se você armazenar muito lixo neles. Além disso, se eles quebrarem sob cargas pesadas (e ocorrerão), você perde informações valiosas; com a maneira de pensar REST, tudo o que acontece nesse caso é que o cliente envia a mesma solicitação (!) novamente e é atendida dessa vez.

Como fazer isso certo então?

Não existe uma solução única para todos. Eu diria que escolha um nível de apátrida e vá com isso. As sessões podem ser amadas por alguns e odiadas por outros, mas não vão a lugar algum. A cada solicitação, envie tantas informações quanto faça sentido, um pouco mais, talvez; mas não interprete a apatridia como não tendo uma sessão, nem como se logando sempre. De alguma forma, o servidor deve saber que é você ; Os IDs de sessão do PHP são uma boa maneira, os tokens gerados manualmente são outra.

Pense e decida, não deixe as tendências de design pensarem em você.

dkellner
fonte
1
"Pense e decida, não deixe as tendências de design pensarem em você." infelizmente, hoje em dia, é muito comum seguir apenas estupidamente as tendências. Às vezes, lendo SO, você obtém as mesmas respostas apenas por causa da tendência.
L00k 6/11/19
Sim, eu já vi isso em vários tópicos e, quando percebo o que está acontecendo, às vezes paro de discutir. Naquela época, todo mundo era louco por como a caixa de conteúdo é melhor que a caixa de borda; era uma maneira de mostrar ódio contra o IE. Então veio o bootstrap e, de repente, todo mundo acreditava nas caixas de fronteira. As tendências vêm, mas depois elas vão. Use goto, use tabelas, use iframes, apenas saiba o que está fazendo e por quê. Os estilistas tentarão derrubá-lo, depois se registrarão e pagarão no seu site. Mundo salvo novamente.
dkellner
@dkellner Eu não entendi essa parte: "O servidor precisa saber pelo menos se alguém está conectado ou não. (E se você incomodar o banco de dados toda vez que precisar decidir isso, estará praticamente condenado.)". Digamos que você armazene dados da sessão no banco de dados com PHP. Por que a consulta ao banco de dados está incorreta (condenada é uma palavra forte), pois, de qualquer maneira, haverá muitas solicitações subseqüentes do banco de dados para obter os dados completos do usuário e outras coisas, com base no ID da sessão do PHP? Em outras palavras, as consultas ao banco de dados são inevitáveis ​​em qualquer caso. Além disso, se você não receber um ID de sessão PHP, você sabe que o usuário não é autenticado, não há necessidade de consultar.
user2923322
Quando você tem milhares ou mesmo milhões de usuários, não pode se dar ao luxo de se conectar ao db toda vez que deseja fazer uma manutenção de atividade, atualização de local, pesquisa de mensagens ou qualquer coisa que precise de um breve check-in. Você precisa implementar essas chamadas sem (ou com o mínimo) acesso ao banco de dados, é por isso que estou dizendo que pode ser letal se você construir todo o seu conceito em torno do db. Novamente, pode haver casos em que uma solução db bem projetada funcione, mas o programador típico resolverá qualquer coisa dizendo "ok, primeiro conectamos e buscamos algumas informações do usuário". Prática Baaaad.
dkellner
5

Dê uma olhada nesta apresentação.

http://youtu.be/MRxTP-rQ-S8

De acordo com esse padrão - crie recursos repousantes transitórios para gerenciar o estado, se e quando realmente necessário. Evite sessões explícitas.

Santanu Dey
fonte
1
Por favor, leia Como escrevo uma boa resposta? antes de tentar responder a mais perguntas.
3

A principal diferença entre sem estado e sem estado é que os dados são sempre transmitidos ao servidor. No caso de apátrida, o cliente precisa fornecer todas as informações para que muitos parâmetros precisem ser passados ​​em cada solicitação. Em Stateful, o cliet passa esses parâmetros uma vez e eles são mantidos pelo servidor até serem modificados pelo cliente novamente.

OMI, API deve ser apátrida, o que permite escalar rapidamente.

psuhas
fonte
2

Você precisa gerenciar a sessão do cliente no lado do cliente. Isso significa que você deve enviar dados de autenticação a cada solicitação e, provavelmente, mas não necessário, possui um cache na memória do servidor, que emparelha os dados de autenticação com as informações do usuário, como identidade, permissões, etc.

Essa restrição de apatridia REST é muito importante. Sem aplicar essa restrição, o aplicativo do lado do servidor não será dimensionado bem, pois manter todas as sessões do cliente será o ponto principal de Aquiles .

inf3rno
fonte
Se você enviar dados de autenticação com cada solicitação, onde / como você armazena as credenciais no cliente para que o usuário não precise digitá-las novamente em todas as solicitações?
28418 Amber
1

Ao desenvolver um serviço RESTful, para fazer login, você precisará que seu usuário seja autenticado. Uma opção possível seria enviar o nome de usuário e a senha sempre que você pretende executar uma ação do usuário. Nesse caso, o servidor não armazenará os dados da sessão.

Outra opção é gerar um ID da sessão no servidor e enviá-lo ao cliente, para que o cliente possa enviar o ID da sessão ao servidor e se autenticar com isso. Isso é muito mais seguro do que enviar nome de usuário e senha toda vez, pois se alguém colocar a mão nesses dados, ele poderá se passar pelo usuário até que o nome de usuário e a senha sejam alterados. Você pode dizer que mesmo o ID da sessão pode ser roubado e o usuário será representado nesse caso e você está certo. No entanto, nesse caso, a representação do usuário só será possível enquanto o ID da sessão for válido.

Se a API RESTful espera nome de usuário e senha para alterar o nome de usuário e a senha, mesmo se alguém se passar por usuário usando o ID da sessão, o hacker não poderá bloquear o usuário real.

Uma identificação de sessão pode ser gerada pelo bloqueio unidirecional (criptografia) de algo que identifica o usuário e adiciona a hora à identificação da sessão, dessa maneira o tempo de expiração da sessão pode ser definido.

O servidor pode ou não armazenar IDs de sessão. Obviamente, se o servidor armazena o ID da sessão, ele violaria os critérios definidos na pergunta. No entanto, é importante garantir que o ID da sessão possa ser validado para o usuário especificado, o que não requer o armazenamento do ID da sessão. Imagine uma maneira de você ter uma criptografia unidirecional de email, ID do usuário e alguns dados particulares específicos do usuário, como cor favorita, esse seria o primeiro nível e, de alguma forma, adicionar a data do nome de usuário à string criptografada e aplicar uma criptografia de maneira. Como resultado, quando um ID de sessão é recebido, o segundo nível pode ser descriptografado para poder determinar qual nome de usuário o usuário afirma ser e se a hora da sessão é certa. Se isso for válido, então o primeiro nível de criptografia pode ser validado fazendo-o novamente e verificando se ele corresponde à string. Você não precisa armazenar dados da sessão para conseguir isso.

Lajos Arpad
fonte
isso faz sentido
iniciada em 13/01
0

O conceito todo é diferente ... Você não precisa gerenciar sessões se estiver tentando implementar o protocolo RESTFul. Nesse caso, é melhor executar o procedimento de autenticação em cada solicitação (considerando que há um custo extra em termos de desempenho - a senha de hash seria um bom exemplo. Não é grande coisa ...). Se você usa sessões - como você pode distribuir a carga em vários servidores? Aposto que o protocolo RESTFul tem como objetivo eliminar as sessões - você realmente não precisa delas ... É por isso que é chamado de "sem estado". As sessões são necessárias apenas quando você não pode armazenar nada além de Cookie no lado do cliente após a solicitação de solicitação (use um navegador antigo, que não suporta Javascript / HTML5 como exemplo). No caso de um cliente RESTFul "com todos os recursos", geralmente é seguro armazenarbase64(login:password) no lado do cliente (na memória) até que o aplicativo ainda esteja carregado - o aplicativo é usado para acessar o único host e o cookie não pode ser comprometido pelos scripts de terceiros ...

Eu recomendaria estritamente desabilitar a autenticação de cookies para serviços RESTFul ... consulte Autenticação Básica / Digest - isso deve ser suficiente para serviços baseados em RESTFul.

user3857922
fonte
3
O que é a client side (in memory) e como é seguro salvar base64(login:password)no lado do cliente?
RN Kushwaha
1
Nada é definido como "completamente seguro". No entanto, você pode considerar o uso do OAuth2, fornecendo segurança melhor do que salvar a string base64 para a solicitação da API (autenticação básica). Se você optar pela autenticação básica, poderá usar o HTTPS para obter melhor segurança.
Felixwcf 18/05/19
3
RN Kushwaha, esta é a pergunta que ninguém parece querer responder quando diz para parar de armazenar a sessão no servidor e armazená-la no cliente.
21716 BeniRose
0

O REST é sem estado e não mantém nenhum estado entre os pedidos. Os cookies / cabeçalhos do cliente são definidos para manter o estado do usuário como autenticação. Digamos que o nome de usuário / senha do cliente seja validado pelo mecanismo de autenticação de terceiros - gerneação de OTP de segundo nível, etc. Depois que o usuário for autenticado - os cabeçalhos / cookies pararão o ponto final do serviço exposto e podemos assumir o usuário como autenticação, pois o usuário vem com cabeçalhos / cookies válidos . Agora, certas informações do usuário como IP são mantidas no cache e, depois disso, se a solicitação vier do mesmo IP (endereço mac) para os recursos listados, o usuário é permitido. E o cache é mantido por um período específico que é invalidado quando o tempo passa. Portanto, o cache pode ser usado ou as entradas do banco de dados podem ser usadas para manter as informações entre as solicitações.

Amit
fonte
0

Sem estado aqui significa que o estado ou os metadados da solicitação não são mantidos no lado do servidor. Ao manter cada solicitação ou estado do usuário no servidor, isso levaria a gargalos de desempenho. O servidor é solicitado apenas com os atributos necessários para executar operações específicas.

Para gerenciar sessões ou fornecer experiência personalizada aos usuários, é necessário manter alguns metadados ou estado das preferências do usuário provável, histórico de solicitações anteriores. Isso pode ser feito mantendo cookies, atributos ocultos ou no objeto de sessão.

Isso pode manter ou acompanhar o estado do usuário no aplicativo.

Espero que isto ajude!

Sourabh Bhavsar
fonte