Alguém já conseguiu criar uma aplicação para a Web Humana (browser x servidor) que seja totalmente sem estado? Eu tava pensando em como
fazer isso na questão da autenticação do usuário, pois como o browser poderia enviar uma informação de que o cliente está ou não logado para
todos os recursos da minha aplicação que o usuário viesse a acessar. Como fazer isso sem cookies?
Por exemplo, uma pessoa entra na página home do meu site. Não está logada. Todos os links dessa página para os recursos da minha aplicação
não possuem qualquer dado do estado do usuário. Quando o usuário se loga, eu quero exibir uma caixa de ferramentas de usuário logado em cada
página da minha aplicação. Uma mesma requisição na página home, dessa vez com o usuário logado, deve ser capaz de descobrir que o usuário está
logado. Como o servidor não guarda qualquer estado do cliente, todas as requisições do cliente devem ser, agora, acompanhadas de alguma credencial
que o identifique. Mas como incluir essas credenciais para cada link dessa página ?
Você salvaria o token de identificação da pessoa como hidden na página.
Já trabalhei em aplicação assim.
Giulliano
Fala ae meu velho…eu desconheço esse nome “Web Humana” e numa pesquisa no google não me retornou nada sobre qualuqer tipo de conceito que leve esse nome.
Essas respostas levam a uma conclusão:
Não é possível construir uma aplicação totalmente sem estado. O que se pode discutir é qual a melhor maneira de guardar o estado em cada situação.
No caso, o que você quer? Minimizar o armazenamento de estado no cliente? No servidor? Ou simplesmente livrar-se dos cookies?
E você está falando de “estado” de um modo geral (dados que persistem durante uma navegação ou sessão), ou especificamente do identificador de sessão?
Incluir as credenciais em cada link é fácil. O próprio servidor de aplicação usa esse recurso (chama-se URL Rewriting) quando um cliente não aceita cookies. Tudo o que precisa fazer é habilitar no servidor e tomar alguns cuidados, como montar cada link usando <c:url>
No entanto isso não atende a outra situação que você cita: quando o usuário entrar novamente no endereço “home” detectar automaticamente que ele está logado. Isso só com cookies mesmo.
Giulliano
É possível criar uma aplicação sem estado…contanto que você não precisa gerenciar isto.
Veja as implementações RestFul…se não hoouver estado é possível compor diversos serviços com pouco esforço. O problema é que quase sempre queremos/precisamos saber quem está do ’ outro lado da linha’
ThiagoInGuj
Hebert Coelho:
Você salvaria o token de identificação da pessoa como hidden na página.
Já trabalhei em aplicação assim.
Certo, mas como eu incluiria esse token em todos os links da minha página. Via script? Beleza, entao o usuario clica
em um link, mandando o token para o servidor. Mas eu queria que o servidor não guardasse estado dos usuários autenticados,
como ocorre com o jsessionid, pois eu queria uma solução mais escalável, igual ocorre nas autenticações dos serviços REST. O cliente
envia, para cada solicitação, todos os estados necessários para que a solicitação seja resolvida. Eu posso ter centenas de servidores e
qualquer um deles é capaz de processar a requisição do cliente, uma vez que o servidor não guarda o estado atual do cliente.
ThiagoInGuj
Giulliano:
Fala ae meu velho…eu desconheço esse nome “Web Humana” e numa pesquisa no google não me retornou nada sobre qualuqer tipo de conceito que leve esse nome.
Fala amigo! Web Humana é um conceito que eu li no livro Restful serviços web. Nesse livro, segundo os autores, um serviço Restful não deve
usar cookies, pois cookies guardam estado do cliente no servidor, o que contraria um princípio REST, não guardar estado do cliente. Entenda-se estado
aqui como o estado atual que o cliente está na sua aplicação (se está logado ou não, se fez a requisicao x, y e agora deve fazer a requisicao z) O servidor
não deve ter que lembrar dos estados x e y anteriores do cliente.
Hebert_Coelho
ThiagoInGuj:
Hebert Coelho:
Você salvaria o token de identificação da pessoa como hidden na página.
Já trabalhei em aplicação assim.
Certo, mas como eu incluiria esse token em todos os links da minha página. Via script? Beleza, entao o usuario clica
em um link, mandando o token para o servidor. Mas eu queria que o servidor não guardasse estado dos usuários autenticados,
como ocorre com o jsessionid, pois eu queria uma solução mais escalável, igual ocorre nas autenticações dos serviços REST. O cliente
envia, para cada solicitação, todos os estados necessários para que a solicitação seja resolvida. Eu posso ter centenas de servidores e
qualquer um deles é capaz de processar a requisição do cliente, uma vez que o servidor não guarda o estado atual do cliente.
Vc não precisa guardar estado no servidor. Guarde tudo que é da sua aplicação dentro de uma string, serialize e coloque como hidden na página do usuário.
Vai ficar uma string enorme, mas funciona. [=
ThiagoInGuj
Essas respostas levam a uma conclusão:
Não é possível construir uma aplicação totalmente sem estado. O que se pode discutir é qual a melhor maneira de guardar o estado em cada situação.
No caso, o que você quer? Minimizar o armazenamento de estado no cliente? No servidor? Ou simplesmente livrar-se dos cookies?
E você está falando de “estado” de um modo geral (dados que persistem durante uma navegação ou sessão), ou especificamente do identificador de sessão?
Incluir as credenciais em cada link é fácil. O próprio servidor de aplicação usa esse recurso (chama-se URL Rewriting) quando um cliente não aceita cookies. Tudo o que precisa fazer é habilitar no servidor e tomar alguns cuidados, como montar cada link usando <c:url>
No entanto isso não atende a outra situação que você cita: quando o usuário entrar novamente no endereço “home” detectar automaticamente que ele está logado. Isso só com cookies mesmo.
Olá Amigo! Eu tinha esquecido do URL Rewriting. É mesmo, dá pra colocar as credenciais usando c:url em cada link da minha página. Se essas credenciais forem as mesmas credenciais armazenadas no bando de dados do cliente, dá pra enviar uma nova requisicao para qualquer servidor que o servidor vai saber dizer se o usuário está logado ou não. Com isso o servidor pode responder uma representacao que mostre a barra de ferramentas. E aí, dá certo?
ThiagoInGuj
Hebert, não entendi direito o que você quis dizer.
Hebert_Coelho
ThiagoInGuj:
Hebert, não entendi direito o que você quis dizer.
O cara mandou nome e cidade.
você recebe os valores, processa tudo e envia o usuário para outra tela (para selecionar bairro) com os valores nome e cidade hidden e serializado.
Quando ele submeter o form com o valor de bairro ele enviará nome e cidade escondidos. E assim você consegue salvar toda informação necessária.
Olhe no código fonte que tem um tal de view state. Esse cara aí é a informação que ele submete toda hora para o servidor contendo os dados necessários pra o correto processamento.
ThiagoInGuj
Mas isso aí tá indo contra o que eu quero. viewstate não é estado da view do JSF? Isso é o estado do cliente que o servidor tem que guardar. Eu não quero guardar qualquer estado da view, pois esse estado é um estado específico do cliente, em um dado momento. Como escalar isso?
Hebert_Coelho
ThiagoInGuj:
Mas isso aí tá indo contra o que eu quero. viewstate não é estado da view do JSF? Isso é o estado do cliente que o servidor tem que guardar. Eu não quero guardar qualquer estado da view, pois esse estado é um estado específico do cliente, em um dado momento. Como escalar isso?
Não é o servidor que está guardando, quem está guardando é a página do usuário. Ao submeter todos os valores necessários estão na string e não no servidor.
ThiagoInGuj
A idéia do URL Rewriting me pareceu boa. Era o que eu queria mesmo, incluir de alguma forma as credenciais do usuário em cada link de forma que o cliente possa me enviar uma requisicao capaz de ser processada por qualquer servidor. (Sem precisar de réplica de sessão)
ThiagoInGuj
Mas essa viewstate não tem uma correspondente no servidor? Dois servidores diferentes podem receber essa requisicao?
Hebert_Coelho
ThiagoInGuj:
Mas essa viewstate não tem uma correspondente no servidor? Dois servidores diferentes podem receber essa requisicao?
Não. Sim.
ThiagoInGuj
Entendi. É que eu não uso JSF, uso frameworks action based. Com action based parece que URL Rewriting funcionaria bem nesse caso.
Hebert_Coelho
ThiagoInGuj:
Entendi. É que eu não uso JSF, uso frameworks action based. Com action based parece que URL Rewriting funcionaria bem nesse caso.
Apenas sitei o JSF como exemplo. Não precisa construir algo do mesmo porte, mas com a mesma idéias apenas.
Com URL Rewriting pode ficar mau visto por usuários ao ver a URL estranha o tempo todo. Só tome cuidado com isso.
ThiagoInGuj
Seria um hash ao final da URL, mas é meio estranho porque esse é um hash da credencial do usuário que está no link de cada recurso da página. Apesar que é isso que o jsession id também faz às vezes.
Hebert_Coelho
ThiagoInGuj:
Apesar que é isso que o jsession id também faz às vezes.
O que também pode ser configurado.
Você tem as duas opções até agora. Escolha e melhor e cai dentro.
ThiagoInGuj
Valeu pela dica da configuracao do jsession id. Eu sempre quis impedir o jsession id na URL e não sabia que já existe um config no web.xml pra isso.
gomesrod
Puxa, agora vendo o prosseguimento do tópico acho que isso não vai atender tão bem a sua necessidade. O token gerado no URL Rewriting identifica a sessão aberta no servidor, que é justamente o que você está tentando evitar. Ele não manda uma credencial “pura” que depois pode ser entendida por outro servidor (a não ser que estejam em cluster compartilhando a sessão, o que também não é o caso).
Nada impede de você criar sua própria tag de url rewriting, para trabalhar da maneira desejada. Só que aí entramos em outros problemas, tipo: como formatar essa credencial de maneira que ela permaneça segura?
Admin não vai rolar né…
E se transformar num hash é preciso garantir que não dá pra “roubar” esse hash e usar para se autenticar como outra pessoa
ThiagoInGuj
gomesrod, eu usaria o URL Rewriting na mão, através de um filtro de servlet por exemplo. Colocaria a credencial do usuário como um hash, igual está no banco de dados (o hash não a senha pura). A única coisa que seria obrigatória para tudo funcionar é que todas as páginas deverão usar https. O problema é o cache, como o link será embutido em todas as urls, eu não posso deixar o cache habilitado. Talvez se em vez de usar URL Rewriting eu inserir a credencial nos links via javascript isso não seja problema, uma vez que o cache do html não conterá o hash incluído via scritpt.
A
AbelBueno
Alguns comentários aleatórios:
Se você tá pensando em ser tão escalável, descarte a idéia de viewstate. Converse com alguém de .NET webforms e irão te contar o sofrimento de performance que isso vira para Internet. Provavelmente por isso recomendam mais WebForms (e JSF) para Intranets e não Internet.
O grande custo da sessão é armazenar coisas nela, não ter uma sessão em si no servidor. Acho que pode armazenar a sessão num servidor específico (único ou mesmo um cluster) como Memcached ou Redis e dessa forma o servidor que recebe a requisição teria algum lugar único para validar a sessão.
No cliente você poderia usar um cookie mesmo para armazenar o id da sessão, imagino.
Na prática essa arquitetura de não compartilhar nada aumenta a complexidade de um projeto.
Geralmente você só vai partir para essa linha quando realmente tiver essa necessidade.
As vezes em livros é descrito um cenário ideal que nem sempre é viável com suas restrições de tempo e custo.
ThiagoInGuj
Abel, eu não uso JSF e também não gosto da idéia de viewstate.
Só não concordo com você sob o ponto em que não guardar estado no servidor aumenta a complexidade de um projeto. Penso o contrário, pois se o servidor não precisar saber sobre o estado atual do cliente então muitas dores de cabeça de escalabilidade somem. Na verdade o problema está no cliente (browser) que deve enviar todo o estado do cliente na URI e no corpo do HTTP. Quando o cliente é um programa de computador, isso é fácil. Mas quando o cliente é o browser, aí é difícil.
ThiagoInGuj
Só uma retificação sobre o uso de cookies. Prosseguindo a leitura do livro Restful web services, eu me deparei com essa parte:
“A única utilização dos cookies que respeita a REST é aquela onde o cliente está no controle do valor do cookie. O servidor
pode sugerir valores para um cookie usando o cabeçalho Set-Cookie, assim como pode sugerir links para o cliente seguir. Em
algumas aplicações baseadas em navegadores os cookies são criados pelo cliente e jamais enviados ao servidor. O cookie é só
uma embalagem conveniente para o estado de aplicação, que toma o caminho para o servidor na forma de representações e URIS.
Esta é uma utilização para os cookies que está de acordo com a REST.”
Entendi então que eu posso usar cookies desde que seja criado pelo cliente e para o controle do cliente sobre o seu estado atual
na aplicação. Então o cliente pode enviar uma requisição para o servidor colocando na URI, cabeçalhos e/ou corpo HTTP todo esse
estado do cliente para que o servidor consiga processar a requisição.
O que não pode ocorrer é o servidor criar um cookie (um hash de sessão por exemplo) onde o servidor controla o estado do cliente.
javaflex
ThiagoInGuj:
Giulliano:
Fala ae meu velho…eu desconheço esse nome “Web Humana” e numa pesquisa no google não me retornou nada sobre qualuqer tipo de conceito que leve esse nome.
Fala amigo! Web Humana é um conceito que eu li no livro Restful serviços web. Nesse livro, segundo os autores, um serviço Restful não deve
usar cookies, pois cookies guardam estado do cliente no servidor, o que contraria um princípio REST, não guardar estado do cliente. Entenda-se estado
aqui como o estado atual que o cliente está na sua aplicação (se está logado ou não, se fez a requisicao x, y e agora deve fazer a requisicao z) O servidor
não deve ter que lembrar dos estados x e y anteriores do cliente.
O livro nao tem exemplo em alguma tecnologia do que os autores defendem ser o mais correto?
ThiagoInGuj
Eles tem exemplos sim, mas são baseados em clientes automatizados não em browsers. No caso do controle de autorizacao por exemplo, para toda requisicao que necessite de credenciais o cliente deve enviá-la junto a requisição.
Conforme minha penúltima resposta, nós podemos usar cookies gerados pelo cliente para enviar essas credenciais para toda requisicao ao servidor no corpo do http por exemplo. Em toda requisição que necessite de autorização, o servidor obtem essas credenciais e verifica no banco de dados (não em um hash de sessão armazenado no servidor para controlar a sessão do usuário) se a credencial confere.
B
bobmoe
Toda aplicação web tem estado. A questão é se é Stateless ou Stateful.
Uma forma de fazer stateful sem cookies é através de WebSockets:
Acho perigoso, por questões de segurança, mesmo usando https, não ter nenhum controle de autenticação no servidor.
Uma forma facil de fazer isso para permitir de maneira mais simples a escalabilidade era ao menos manter algumas informações sobre a autenticação do usuário (o hash, o ip, o navegador, sistema operacional, etc), armazenadas em um banco de dados. Isso evita ter de configurar replicação de sessão. Um banco de dados NOSQL pode ser uma boa nesse caso!