Tratamento de tempo limite da sessão do usuário em aplicativos SaaS - discutindo várias abordagens


11

Eu sei que isso tem uma grande chance de ser marcado como duplicado, mas não consegui encontrar exatamente o que estou procurando

Esse é um problema comum e tenho certeza de que possui uma solução de melhores práticas bem definida

fundo

  1. Um aplicativo SaaS de página única, com muito arrastar e soltar, o usuário pode interagir com ele sem muita comunicação com o servidor por períodos de tempo

  2. A sessão do servidor mantém apenas o objeto do usuário, usando um cookie de sessão não persistente

  3. A sessão expira no servidor após X horas

  4. Algumas coisas são carregadas apenas durante o login

Problema

  1. O usuário trabalha no aplicativo; quando concluído, o usuário não efetua logout, apenas mantém o navegador aberto
  2. O usuário volta após mais de X horas (a sessão é invalidada no servidor)
  3. O usuário interage com o aplicativo sem precisar de uma conexão com o servidor (arrasta e solta itens, edições de texto ...)
  4. Somente na próxima interação do servidor (suponha que não haja salvamento automático) o usuário é lançado na página de login e perde parte do trabalho

Soluções possíveis

Aqui estão algumas soluções que eu tenho em mente, gostaria de saber se existem outras, e se há algo fundamentalmente errado com alguma delas.

1. Nunca desconecte o usuário

  • Como? mantenha uma sessão longa, mantenha um cookie persistente ou javaScript "keep alive" ping
  • Prós : o usuário não precisa se preocupar com nada, corrige o problema para eles
  • Contras : não é compatível com PCI, não é seguro e precisa de alterações no desenvolvimento, por exemplo, coisas carregadas na sessão apenas no logon do usuário precisam passar para um submodelo de publicação (ouvindo alterações de eventos) ou ter tempo limite de cache.

2. Armazenamento local

  • Como? use o novo armazenamento local para armazenar temporariamente o estado se estiver desconectado, redirecione para a página de login, persista após o login
  • Prós : Baseie -se também no suporte ao "trabalho offline", e não apenas ao lidar com o tempo limite da sessão
  • Contras : mais difícil de implementar, precisa mesclar estado da árvore de dados, nem todos os navegadores suportam

3. Salvamento automático

Toda ação do usuário que altera o modelo deve persistir imediatamente (ou através de algum tipo de fila do lado do cliente), por exemplo, se marcar uma caixa de seleção, alterar um campo de texto ou arrastar e soltar algo, após concluir, persistem as alterações.

  • Como? Use uma estrutura MV ** (Backbone.js / Knockout.js / Ember.js / Angular.js etc) para vincular o modelo e persistir nas alterações.
  • Prós : Parece uma solução limpa, a sessão fica ativa enquanto o usuário estiver ativo, nenhum trabalho do lado do cliente é feito sem persistir.
  • Contras : A última ação do usuário após a perda de um tempo limite da sessão.

4. Desconecte o usuário após o término da sessão

isso pode ter várias abordagens

  1. Pergunte ao servidor "a sessão expirou" - isso é um pouco complicado para o gato de 22 / Schrodinger, pois a mera pergunta ao servidor estende a sessão (reinicia o tempo limite),

    • Como? Você tem um servidor que suporta essa pergunta (não conheço nenhuma, mas venho do Java land) ou pode-se manter uma tabela de IDs de sessão e o último horário de acesso manualmente e perguntar ao servidor passando a sessão O ID como parâmetro, em vez do cookie, não tenho certeza se isso é possível, mas parece perigoso, inseguro e com design inadequado de qualquer página.login, persiste após o login
    • Prós : se houver esse suporte nativo nos servidores, isso soa como uma pergunta limpa e legítima (perguntar se o usuário X ainda tem uma sessão ou não, sem renová-la, se houver)
    • Contras : Se o servidor não o suportar (e novamente, não sei se algum servidor ou estrutura tem essa funcionalidade), a solução alternativa apresenta enormes riscos à segurança.
  2. Uma solução alternativa que ouvi foi ter uma sessão curta no lado do servidor e um ping ativo no lado do cliente, com um número máximo de pings

    • Como? Sessão curta no servidor, o cliente faz ping em cada sessionTimeOut / 2, tem tentativas máximas de Y.
    • Prós : tipo de solução do problema, rápida e suja
    • Contras : Parece um hack, manipular você mesmo a renovação da sessão, em vez de permitir que o servidor faça isso
  3. Temporizador do lado do cliente

    • Como? Tenha um cronômetro no lado do cliente e sincronize-o com o servidor, reiniciando-o em cada solicitação para que seja igual ao tempo limite máximo da sessão do servidor menos algum preenchimento, depois que o usuário não enviar nenhuma solicitação ao servidor, a interface do usuário mostrará "sessões são prestes a expirar, você deseja continuar? " (como você tem no banco on-line)

    • Prós : corrige o problema

    • Contras : Não consigo pensar em nada, exceto na necessidade de garantir que a sincronização funcione

A questão

Provavelmente estou perdendo algo na análise acima, pode haver alguns erros tolos e gostaria que sua ajuda para corrigi-los. Que outras soluções posso ter para isso?


Eu uso angular e django com tastypie, então aqui estão meus pensamentos desse ponto de vista: 4.1: A classe de autenticação usada para todos os seus recursos poderia verificar e comparar a diferença de tempo entre agora e o valor do campo "último acesso" em seu usuário modelo. 401 é que o tempo é maior que o período configurado. 200 caso contrário, e atualize o campo 'último acesso' com now. 4.2 parece uma ótima maneira de matar o servidor e aumentar os custos 4.3 No Android, ao retornar à tela inicial, tenho certeza de que o processo está em pausa e que também pode interferir no timer do cliente.
Airtonix #

Respostas:


5

Eu acho que a solução simples mais comum é onde você define um timer no final do cliente que mostra uma mensagem depois que uma certa parte da janela de tempo limite normal passou e, em seguida, efetua o logout forçado antes que a sessão expire de qualquer maneira, se eles não tomarem nenhuma ação.

O armazenamento local e o salvamento automático apresentam alguns problemas nas transações e o que realmente significa salvar. Já participei de vários projetos nos quais isso acabou sendo mais problemático do que vale quando a base de usuários não entende a mecânica por trás disso.

Nunca fazer logout pode ser feito onde as regulamentações o permitirem, mas isso leva a erros quando você não lida corretamente com o que acontece se alguém for desconectado inesperadamente, e todos os negócios do estado se tornam um pouco intensos para manter, se houver muito o que rastrear um usuário "ativo".


2

Uma solução alternativa que ouvi é ter uma sessão curta no lado do servidor e um ping no lado do cliente keep alive, com um número máximo de

Como? Sessão curta no servidor, o cliente faz ping em cada sessionTime / 2, tem no máximo> tentativas de Y. Prós: Tipo de correção do problema, rápido e sujo Contras: Parece um hack, manipula a renovação da sessão você mesmo, em vez de deixar o servidor fazê-lo

Esta é, na minha opinião, a melhor solução. Por que você considera um "truque sujo"?

Faz exatamente o que precisa ser feito. Enquanto o usuário trabalha com o programa, a sessão permanece aberta.

Depois que o usuário parar para trabalhar com o programa, a sessão será fechada.

Simples o suficiente para ser implementado.

Exatamente o que é necessário, se eu entendi a pergunta corretamente.


Às vezes, os hacks sujos são as melhores soluções :) obrigado. Você entendeu a pergunta perfeitamente certo
Eran Medan

2

Na verdade, estou criando um aplicativo que lida com isso.

Comecei criando um serviço RESTful usando Django, Guradian e Tastypie. Autentica usando apenas APIKEY, a autorização para objetos é manipulada pelo Guardian.

O aplicativo django possui apenas um urlconf de visualização de modelo que carrega o base.html, que é ...

No lado do cliente, criei um aplicativo usando Angular.

No que diz respeito à autenticação, existe um http-auth-interceptor que escuta 401 respostas.

Quando um 401 é recebido, ele armazena em buffer a solicitação de saída e dispara um evento "requerido login". Isso pode ocorrer várias vezes.

Eu tenho um pop-up modal contendo um formulário de logon que é apresentado quando o evento "necessário para o logon" é ouvido e ele executa um logon que retorna um recurso de Usuário (um pacote JSON) que também conteria o APIKEY.

Todas as solicitações em buffer que anteriormente resultaram em uma resposta 401 são repetidas com o APIKEY agora incluído no cabeçalho http da Autorização.

Uso outro serviço / fábrica angular para gerenciar dados json de armazenamento local, e é aí que armazeno o nome de usuário e o apikey.

A única peça do quebra-cabeça a ser resolvida é como proteger essas informações e como aplicar um tempo limite a essas informações.

Talvez use uma verificação de data e hora da última solicitação http válida.


Como acompanhamento disso, considerei fazer a seguinte comparação em cada verificação de autenticação saborosa: current_time> user.lastlogin_time + settings.SESSION_TIMEOUT. em seguida, retorne 401 se verdadeiro. Cada autenticação válida atualiza o user.lastlogin_time para current_time.
Airtonix

Isso é muito bom e como eu também pensei em lidar com isso.
Oligofren

1

No meu caso, estou usando algo semelhante ao 4.1. Depois que o usuário efetua login, uma solicitação json AJAX direcionada angular muito leve ocorre na API REST em intervalos definidos no servidor. Por causa dos requisitos de segurança, a interface do usuário proprietária antecipa que o servidor manterá uma sessão para o usuário que armazena algumas informações, modelos, dados etc. protegidos no lado do servidor. Este ainda é o meu método preferido do ponto de vista de segurança. Ao lidar com dados confidenciais (não apenas senhas com hash e outros), a IMO armazená-lo do lado do cliente no armazenamento local etc. apresenta um risco maior que o do servidor (tenho certeza de que alguém debateria isso comigo). Terceiros usam a mesma API ao se comunicar com o sistema, mas devem enviar credenciais de autenticação em cada solicitação.

A sessão no servidor tem uma vida útil máxima ociosa aplicada e o mecanismo de armazenamento da sessão é armazenado em cache (o que também possui uma vida útil máxima aplicada no momento em que a sessão de memória será marcada como expirada). O tempo de vida só precisa ser maior do que o tempo de vida da sessão que você abstrai em seu aplicativo (e não precisa ser o meu valor). A sessão pode não expirar até ficar inativa por 48 horas no que diz respeito ao servidor, mas seu código controla a vida útil real. Isso pode levar a problemas de recursos se essa vida útil for muito grande e você fizer um péssimo trabalho no gerenciamento das sessões.

No meu caso, usuários diferentes podem ter diferentes tempos limite de sessão inativos com base em suas funções na organização. O servidor coloca limites máximos no tempo de vida da sessão, mas, desde que os limites definidos pelo usuário sejam menores que esses, ele funcionará perfeitamente. Depois que o servidor expira a sessão, é um problema discutível, pois o processo de expiração da sessão já teria sido tratado pelo aplicativo normalmente. Esse é um requisito do tipo de aplicativo de negócios que eu criei.

Depois que a sessão do usuário estiver ociosa e dentro de um limite especificado pelo aplicativo, a API instruirá a interface do usuário a exibir uma caixa de diálogo de contagem regressiva (como os bancos), e uma vez dentro de uma margem específica de distância no tempo desde a expiração, normalmente desconecta o usuário. Essa funcionalidade persiste nas janelas do navegador (porque o servidor está no controle) e um evento inativo em qualquer janela iniciará o temporizador gracioso e o processo de logout automatizado (e os manterá sincronizados).

Se por acaso a sessão expirar de maneira desagradável (as sessões são despejadas no cache de memórias), a próxima solicitação que afeta o servidor notificará o usuário e os moverá de volta à estaca zero (raramente acontece, mas pode).

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.