Como fazer autenticação sem estado (sem sessão) e sem cookies?


107

Bob usa um aplicativo da web para conseguir algo. E:

  • Seu navegador está em dieta, portanto não suporta cookies .
  • A aplicação web é popular, lida com muitos usuários em um determinado momento - tem que escalar bem. Contanto que manter a sessão imponha um limite para o número de conexões simultâneas e, é claro, trará uma penalidade de desempenho não desprezível , gostaríamos de ter um sistema sem sessão :)

Algumas notas importantes:

  • temos segurança de transporte ( HTTPS e seus melhores amigos);
  • por trás das cortinas, o aplicativo da web delega muitas operações para serviços externos , em nome do usuário atual (esses sistemas reconhecem Bob como um de seus usuários) - isso significa que temos que encaminhar a eles as credenciais de Bob .

Agora, como autenticamos Bob (em cada solicitação)? Qual seria uma forma razoável de implementar tal coisa?

  • jogar tênis com as credenciais via campos ocultos do formulário HTML ... a bola contém as credenciais ( nome de usuário e senha ) e as duas raquetes são o navegador e o aplicativo da web, respectivamente. Em outras palavras, podemos transportar dados de um lado para outro por meio de campos de formulário em vez de cookies. A cada solicitação da web, o navegador publica as credenciais. Embora, no caso de um aplicativo de página única , isso possa parecer como jogar squash contra uma parede de borracha, em vez de jogar tênis , já que o formulário da web que contém as credenciais pode ser mantido vivo durante toda a vida da página da web (e o servidor será configurado para não oferecer as credenciais de volta).
  • armazenar o nome de usuário e a senha no contexto da página - variáveis ​​JavaScript etc. Página única necessária aqui, IMHO.
  • autenticação baseada em token criptografado. Nesse caso, a ação de login resultaria na geração de um token de segurança criptografado (nome de usuário + senha + outra coisa). Este token seria devolvido ao cliente e as próximas solicitações seriam acompanhadas pelo token. Isso faz sentido? Já temos HTTPS ...
  • outras...
  • último recurso: não faça isso, armazene as credenciais na sessão! A sessão é boa. Com ou sem cookies.

Você tem alguma preocupação com a web / segurança em relação a alguma das ideias descritas anteriormente? Por exemplo,

  • limite de tempo - podemos manter um carimbo de data / hora , junto com as credenciais (carimbo de data / hora = a hora em que Bob inseriu suas credenciais). Por exemplo, quando NOW - timestamp> threshold , podemos negar a solicitação.
  • Proteção de script entre sites - não deve ser diferente de forma alguma, certo?

Muito obrigado por reservar um tempo para ler isso :)


1
Você pode anexar um token a cada URL. ASP.NET tem um modo (legado) para fazer isso. Isso prova que pode funcionar.
usr

1
Onde está todo mundo? :)
turdus-merula

2
Acho que você tem uma boa ideia das opções disponíveis. Confie no seu raciocínio e decida você mesmo.
usr

é um plugin como o silverlight do flash uma opção?
Giu de

@usr não tem certeza se é uma boa ideia, já que um hacker acessar seus logs de servidor web pode roubar seu token e entrar em seu sistema.
GibboK

Respostas:


74

Ah, eu amo essas perguntas - manter uma sessão sem uma sessão.

Eu vi várias maneiras de fazer isso durante minhas temporadas durante as avaliações de aplicativos. Uma das formas populares é a forma de jogar tênis que você mencionou - enviar o nome de usuário e a senha em cada solicitação para autenticar o usuário. Isso, na minha opinião, não é seguro, especialmente se o aplicativo não for uma página única. Também não é escalonável, especialmente se você quiser adicionar autorização ao seu aplicativo, além da autenticação no futuro (embora eu ache que você também possa construir algo baseado em logins)

Um mecanismo popular, embora não completamente sem estado (assumindo que você tenha a execução de JavaScript), é incorporar o cookie de sessão no JavaScript. O cara da segurança em mim está gritando com isso, mas poderia realmente funcionar - cada solicitação tem umX-Authentication-Tokencabeçalho ou algo parecido, e você mapeia para um banco de dados, armazenamento de arquivos na memória, etc. no backend para validar o usuário. Este token pode ter um tempo limite de qualquer hora que você especificou e, se ele expirar, o usuário terá que fazer login novamente. É bastante escalável - se você armazená-lo em um banco de dados, sua única instrução SQL é executada e, com os índices corretos, deve levar muito pouco tempo para ser executado, mesmo com vários usuários simultâneos. O teste de carga aqui definitivamente ajudaria. Se eu li a pergunta corretamente, este seria o seu mecanismo de token criptografado - embora, eu sugiro fortemente que você use um token criptograficamente aleatório de, digamos, 32 caracteres, em vez de usar uma combinação de nome de usuário + senha + qualquer outra coisa - desta forma, ele permanece imprevisível, mas você ainda pode associá-lo ao ID do usuário ou algo parecido.

Independentemente do que você acabar usando, certifique-se de que seja enviado a você com segurança. HTTPS protege você através do fio, mas não o protege se você vazar o token de sessão por meio do URL (ou pior, credenciais por meio do URL). Eu recomendaria usar um cabeçalho ou, se isso não for viável, enviar o token por meio de uma solicitação POST todas as vezes (isso significaria um campo de formulário oculto no navegador do usuário). A última abordagem de usar uma solicitação POST deve usar defesas CSRF, apenas no caso, embora eu suspeite que usar o próprio token pode ser algum tipo de defesa contra CSRF.

Por último, mas não menos importante, certifique-se de ter algum mecanismo no back-end para limpar tokens expirados. Isso tem sido a ruína de muitos aplicativos no passado - um banco de dados de tokens de autenticação em rápido crescimento que parece nunca desaparecer. Se você precisar oferecer suporte a vários logins de usuário, certifique-se de limitar o número ou de limitar o tempo de cada token. Como eu disse antes, o teste de carga pode ser a resposta para isso.

Posso pensar em algumas outras questões de segurança, mas são muito amplas para serem abordadas neste estágio - se você mantiver todos os casos de uso (e abuso) em mente, provavelmente será capaz de fazer uma implementação razoavelmente boa de este sistema.


Você não pode fazer o que o framework play faz e enviar um cookie assinado para o usuário? Então esse cookie é enviado de volta ao servidor para cada solicitação subsequente?
j será

8
> Seu navegador está em dieta, portanto, não suporta cookies.
Karthik Rangarajan

4
Alguma dessas sugestões é realmente sem estado / sem sessão ? Dos seus cinco parágrafos principais (a partir da edição de 2013-12-19 do post): o nº 1 é introdutório, o nº 2 propõe sessões extra-kludgy Web2.0 ™, o nº 3 são apenas advertências, o nº 4 discute as implicações de statefulness , e # 5 é um outro vago ... como isso foi aceito ?? É tangencialmente informativo na melhor das hipóteses!
JamesTheAwesomeDude

1

Sobre a opção de log-in - acho que normalmente você quer apoiar sessões também para convidados.

Portanto, se você deseja impor o login, a opção de token criptografado pode ser boa. Pode ser bom também para uma sessão de convidado de alguma forma. Em outra direção, eu combinaria entre anexar o token ao URL e a opção de tênis.

Observe que enviar credenciais apenas na URL pode ser perigoso. Por exemplo, você pode vazar o token por meio do cabeçalho de referência HTTP ou mesmo por alguém que apenas inspecione seu tráfego ou observe seu computador.

Outra coisa, mesmo se você pudesse usar cookies, eu recomendo que você adicione token aleatório ou verificador aleatório, para se proteger de ataques Cross Site Request Forgery (CSRF).


3
Uma sessão é o estado armazenado no servidor. A pergunta pede autenticação sem estado.
Kwebble de
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.