Autenticação e Segurança

Olá pessoal! Esta semana quero falar de um assunto de infra-estrutura, mas extremamente crítico em nossas aplicações: a parte de autenticação e segurança de usuários. Quando fazemos uma aplicação Web, temos que definir como nossos usuários serão autenticados. Os desenvolvedores felizes são aqueles que utilizam autenticação integrada em suas aplicações e deixam a cargo da rede e do Active Directory (AD) a tarefa de identificar quem está logado. Claro que isto funciona bem em ambiente de Intranet. Na Internet é até possível, mas em geral é uma alternativa que não é utilizada por consumir uma banda excessiva e ser estranho para o usuário, abrindo aquela tela de login Windows cada vez que se acessa um site. Existe ainda a autenticação básica, utilizada em sites HTTPS e que basicamente mapeia o usuário logado para um usuário de rede. Esta alternativa também consome bastante banda e é pouco amigável para o usuário.

Nos cenários comuns, a autenticação é feita diretamente pela aplicação e o usuário se depara com campos de “login/senha” em alguma página da aplicação Web. Nestes casos, o mecanismo mais usado no .NET é o FormsAuthentication, com cookies. Nesta modalidade, após fornecer uma combinação login/senha válida, o sistema cria um cookie que é utilizado para autenticar as requisições subsequentes do usuário. Este cookie é associado à web session do usuário (na verdade, ele serve para “amarrar” a sessão, identificando-a a partir de sua criação) e permanece válido pelo tempo definido de expiração – normalmente 30 minutos. É possível ter FormAuthentication no formato cookieless, mas é menos utilizado por ser menos seguro.

Usar o FormsAuthentication (com cookies) no .NET é algo relativamente simples, todo o trabalho é feito pelo próprio framework. Para a maior parte dos sistemas, isto atende completamente a necessidade de autenticação. Em sistemas um pouco maiores, é possível também incluir uma implementação do security membership provider (ver estes excelentes posts aqui sobre o assunto), e ter a definição de perfis por usuário, resolvendo também as necessidades de autorização. É possível encontrar na web vários exemplos de implementação até com algumas customizações destes providers, como esta aqui fazendo uso de WCF.

Os problemas começam a surgir quando a aplicação cresce ao ponto de ter que ser integrada a outros sistemas e plataformas ou ter que coexistir com outras, ou ainda ter que suportar múltiplas formas de acesso (Windows Forms p. ex.). Nestes casos, temos que ter maneiras alternativas para identificar usuários e até fazer transferências de uma aplicação para outra. Em grandes empresas, surgem necessidades como definir uma política de segurança de expiração de senhas, um banco de dados único para os usuários entre as aplicações e até a necessidade de fazer login integrado ao AD em algumas situações. Aplicações de maior porte podem também necessitar de melhor desempenho na infra-estrutura de segurança, já que isto é utilizado em praticamente todos os requests. Finalmente, em aplicações corporativas é usualmente necessário ter coletas de estatísticas de uso e usuários ativos, para efeito de monitoramento e planejamento de carga. Nestes casos, a implementação padrão de segurança pode não atender completamente e é necessário desenvolver uma própria.

No nosso caso, desenvolvemos uma solução de segurança que já está em uso há mais de 12 anos. É uma solução WCF bastante simples, com um banco de dados de usuários, perfis e aplicações, classificados por empresa. Os serviços expõem mecanismos de autenticação direta por senha e por integração ao AD. A senha não é armazenada, utilizamos um hash gerado pelo próprio .NET. A integração ao AD é algo simples ainda, baseado no ID de rede (só liberamos para algumas poucas aplicações, onde o ambiente é controlado e os riscos baixos), há planos de se utilizar o Federated Services para algo mais avançado. Todo o acesso aos serviços são feitos por um intermédio de um agente de segurança, que implementa as classes de segurança e faz a tradução para os DTOs do WCF. O sistema suporta políticas de segurança, complexidade e expiração de senhas e coleta todas as estatísticas de uso das aplicações.

A solução possui ainda métodos para suportar a geração de tokens de segurança. Este tokens são identificadores (guid) que são passados, via querystring ou qualquer outro mecanismo, de um aplicação para outra. Eles possuem uma expiração rápida e podem ser utilizados apenas uma vez. Cada token está associado à sessão do usuário que o criou e pode ser utilizados para permitir o login rápido em outra aplicação. Com isto, conseguimos fazer a transferência de uma aplicação para outra de maneira transparente para o usuário.

Todos os nossos sistemas fazem uso da mesma solução de segurança, sempre através da utilização do agente. O FormsAuthentication continua sendo usado, a diferença é que a identificação do usuário é feita por nossa solução, não utilizando o membership provider. A única coisa que fazemos na aplicação é implementar classes para encapsular as chamadas ao agente e utilizar a session do ASP.NET para armazenar o usuário ativo e as respectivas permissões. Isto garante um melhor desempenho, evitando que a cada request os dados do usuário e respectivos perfis tenham que ser obtidos via chamadas WCF.

Aplicações Windows também utilizam o agente de segurança. A diferença é que como não temos um SessionID, como na Web, acabamos por simular um criando uma chave guid cada vez que a aplicação é inicializada. Esta chave é utilizada como se fosse o identificador daquela sessão Windows e pode também ser usada para se gerar tokens de autenticação. Assim é possível, por exemplo, clicar em um botão de uma aplicação Windows Form e se abrir um browser, com uma página de uma aplicação Web, já autenticada.

É isto, espero ter dado uma idéia de como lidamos com autenticação e autorização em nossos sistemas. Se alguém tiver alguma dúvida específica, basta entrar em contato. Até a próxima!

, ,

  1. #1 por tucaz em 21/01/2011 - 4:25 pm

    Massa!

    Em uma das empresas que trabalho utilizamos exatamente o mesmo modelo que você descreveu no post. A unica diferenca é que ainda estamos com Webservices ao invés de Wcf.

    Na minha opinião, este tipo de solucão é a melhor maneira de se lidar com este tipo de problema dentro de uma corporacão com diversas apps.

    Great post! 🙂

  2. #2 por Frederico B. Emídio em 24/01/2011 - 10:05 am

    Olá Alexandre, muito bom artigo.

    Só gostaria de comentar que existe alguns riscos em armazenar informações de acesso em Sessions normais do Asp.Net, pois ela são mais facilmente roubadas, ou mais difíceis de gerenciar em ambientes de Farms.

    Além de que o timeout do FormsAuthentication é diferente do de Session

    Esse artigo fala um pouco disso: http://msdn.microsoft.com/en-us/library/ff648341.aspx

    Procurei um artigo mais detalhado que li há muito tempo atrás, mas não achei.

    Abraços,
    Frederico

    • #3 por Alexandre Valente em 24/01/2011 - 2:49 pm

      Oi Frederico,

      De fato, os timeouts são diferentes e realmente é necessário levar ambos em consideração quando se armazena dados do usuário em sessão. Quanto ao risco de obter dados de sessão, ele é quase nulo quando se usa SSL (só se tiver algum bug mais sério na sua aplicação mesmo). Em cenários sem SSL vc tem que ser realmente mais cauteloso… Quanto ao farm, vc pode ter que configurar um servidor externo (o que tem implicações em desempenho) ou usar outro mecanismo…

      Obrigado pelo link e pelo comentário!

  1. Tweets that mention Autenticação e Segurança « Alexandre Valente's Blog -- Topsy.com

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: