Fernando Correia

Usuários do ASP.NET em Worker Roles do Azure

In Dicas on 3 abr 2012 at 21:51

fingerprint_604

Para garantir a escalabilidade e a velocidade de resposta de uma aplicação web na nuvem, um padrão de projeto recomendado é separar a camada web (front-end) da camada de processamento (back-end).

No Azure, uma das melhores formas de fazer isso é usar a fila de mensagem do Queue Storage para que a camada web (Web Role) envie comandos para serem executados pelos servidores da camada de processamento (Worker Role).

Existem vários tutoriais sobre o assunto, mas uma questão importante nem sempre é abordada, que é o tratamento da segurança destas mensagens.

Uma prática que eu recomendo é não trafegar estas mensagens de forma anônima, mas salvar nelas a identificação do usuário cuja solicitação causou a sua geração. Assim a camada de processamento pode saber qual usuário gerou a mensagem; se for desejável, pode validar novamente a sua autorização para esta execução, aplicando o padrão de defesa em profundidade. E pode também realizar registros de auditoria para associar as operações executadas ao usuário que as solicitou.

Eu vou sugerir uma forma prática de transferir estas informações de identidade e autorização entre as camadas front-end e back-end.

Gestão de usuários do ASP.NET

Já há muitos anos o ASP.NET possui recursos de gestão de usuários bastante completos e maduros. Estes recursos formam um conjunto:

  • Membership: Responsável pela gestão de identidades de usuários e pelas suas senhas.
  • Roles: Recursos de autorização baseada em papéis.
  • Profile: Gerenciamento de perfis de usuário, permitindo associar dinamicamente informações diversas aos usuários.

Esses recursos são utilizados pela autenticação baseada em formulários do ASP.NET (Forms Authentication), mas são independentes dela. Existe inclusive um conjunto de classes no namespace System.Web.ApplicationServices que permite utilizar estes recursos como serviços WCF.

Apesar de antigo, esta facilidade está longe de ser obsoleta. Inclusive, foi recém-lançado o System.Web.Providers, que permite armazenar estas informações em diversos bancos, desde o SQL Compact Edition até o SQL Azure.

Este recurso é muito usado e é comum encontrar aplicações web ASP.NET que gerenciem seus usuários usando Membership, Roles e Profiles.

E daí surge a questão: se o meu usuário está sendo gerenciado pelo ASP.NET, como eu posso passar a sua identificação através de uma mensagem e conseguir recuperá-lo em um Worker Role, que não é uma aplicação ASP.NET?

Usuários do ASP.NET fora do ASP.NET

Felizmente, o ASP.NET não é monolítico, mas é um conjunto de recursos que cooperam entre si mas são, até certo ponto, independentes. Inclusive, esta característica de arquitetura está sendo ainda mais reforçada na versão do ASP.NET que está em desenvolvimento.

O fato é que os providers de Membership, Roles e Profile funcionam de forma independente do IIS e do ASP.NET. Eles podem ser incluídos praticamente em qualquer tipo de aplicação, seja console, serviço, Windows Forms, WPF, testes unitários, etc. Podem, inclusive, ser incluídos em um Worker Role que roda no Azure e processa mensagens, sem nem ter o IIS instalado!

Como fazer

Não é difícil, mas é preciso um pouco de coragem para sair do convencional. Você vai incluir assemblies como System.Web e System.Web.ApplicationServices em seu projeto não-web. Nada tema, lembre-se que assemblies simplesmente acrescentam classes ao seu projeto. Ele não vai passar a depender do IIS ou ASP.NET por causa disto.

Mais estranho e radical ainda, você vai acrescentar uma seção <system.web> ao seu app.config! Nessa seção, você vai declarar os elementos <membership>, <profile> e <roleManager>, como em um website. Na verdade, o ideal é você copiar estas declarações do web.config para dentro do app.config. Não se esqueça de copiar também a string de conexão.

Uma dica importante de configuração: existe uma pequena diferença de comportamento entre um website e uma aplicação de outro tipo. Se você usa uma classe customizada de perfil de usuário, a declaração desta classe precisará incluir não apenas o nome completo da classe, mas também o nome da assembly em que ela se encontra (“Nome.Da.Classe, Nome.Da.Assembly”). Caso contrário, a classe não será encontrada. Eu perdi algum tempo até descobrir isto!

Feitas estas configurações, você pode usar as funcionalidades de usuários do ASP.NET em sua aplicação. Tanto para ler informações de usuários, papéis e perfis, como até mesmo para criar usuários ou alterar senhas, se fizer sentido.

Estes são os principais métodos:

Neste momento eu não estou fornecendo um código de demonstração, mas com as dicas acima você já consegue implementar.

Identidade de ponta a ponta

Em resumo, se a sua aplicação usa a gestão de usuários do ASP.NET e também usa mensagens para realizar processamento assíncrono e desacoplado em servidores de back-end, você tem como passar a identificação destes usuários nas mensagens, e recuperar as informações de usuários nos servidores de back-end, lidas diretamente da base de dados de usuários do ASP.NET.

Eu fiquei bem satisfeito com esta solução. E você, o que achou? Continue a conversa nos comentários abaixo ou pelo Twitter.