Por Dennes Torres
dennes@bufaloinfo.com.br
Dennes Torres possui as certificações MCAD, MCSD,MCSE, MCDBA e MCT.
Atualmente atua como diretor da Búfalo Informática, líder
do grupo de usuários DevASPNet, co-lider dos grupos devSQL e getWindows no Rio de Janeiro, podendo sempre ser encontrado na lista de discussão do grupo DevASPNet
(devaspnet-subscribe@yahoogrupos.com.br) bem como nas reuniões do grupo. Possui também um blog em http://cidadaocarioca.blogspot.com

Sistema de autorização no .NET 2.0



O design pattern de Providers transformou o desenvolvimento de software em um verdadeiro LEGO. Para identificar usuários utilizamos um Membership provider, podendo escolher entre diversos memberShipProviders que existem.

Por exemplo, autenticação com o Active Directory. Tipicamente isso é feito utilizando protocolos de autenticação integrada entre o browser e o servidor web. Se o browser não suporta esses protocolos, a autenticação não se realiza.

Com o uso dos providers podemos apontar a autenticação para o active directory e continuar utilizando os objetos tradicionais de autenticação, como o login, loginView, entre outros webControls. Com isso conseguimos configurar uma autenticaçã com o active directory sem a necessidade de utilizar nenhum código.

Para identificar grupos a que os usuários pertencem podemos utilizar o Role Manager e Role Providers, também permitindo que os grupos fiquem em qualquer local, de acordo com os providers escolhidos. Podemos utilizar os grupos do ActiveDirectory ou armazenar os grupos em uma estrutura de banco padrão. Claro, podemos ainda criar um roleProvider personalizado para utilizar nossa própria estrutura para isso.

Usuários e grupos de usuários, portanto, utilizam o sistema de providers, sendo então altamente configuráveis com relação a obtenção dos dados e mantendo a criação da interface de forma padrão.

Para completar o cenário de segurança, porém, falta um conjunto de informações muito importantes : As informações de autorização, ou seja, quem pode acessar o que.

A autorização padrão pode ser configurada através das páginas de administração do site, que são chamadas pelo visual studio. As configurações realizadas, porém, são gravadas fisicamente dentro dos arquivos web.config. Para cada pasta na qual tenhamos feito a configuração de autorização, é criado um web.config para aquela pasta, contendo as informações de autorização.

A ferramenta de administração apenas permite configurar permissões nas pastas. Para configurar permissões a nível de arquivo precisamos recorrer a uma edição direta do web.config. Veja uma atribuição de permissões de acesso a um arquivo :

<location path="arquivo.aspx">
<system.web>
<authorization>
<allow roles="Admins" />
<deny users="*" />
</authorization>
</system.web>
</location>

Neste exemplo apenas usuários pertencentes ao grupo Admins tem acesso a página "arquivo.aspx". Todos os outros não tem permissão de ver esta página.

Todo isso que vimos vai até o nível da página, ou seja, definir quem pode ou não acessar uma página. Para definir quem pode ou não ver um determinado objeto dentro da página a coisa fica ainda mais complicada.

Nesse caso o sistema de autorização não nos fornece recurso algum. Precisamos por conta própria - e por código - verificar se o usuário encontra-se ou não dentro de determinado grupo.

Por exemplo :

Objeto.Visible=context.User.isInRole("Admins")

Neste exemplo o objeto poderá estar visível ou não na página dependendo do usuário estar ou não contido no grupo de administradores.

Vamos resumir os vários problemas que esse sistema de autorização possui :

1) Não controla objetos dentro de uma tela (página), deixando isso a cargo do desenvolvedor.

2) Interliga diretamente grupos de usuários com as permissões que estes grupos possuem, fazendo com que a manutenção de segurança - mudança dos grupos existentes, reorganização dos usuários - fique complexa.

3) A configuração das permissões ficam em arquivos .CONFIG, de dificil manutenção. Seria interessante que administradores de negócio (gerentes, diretores) determinassem a organização de segurança ou parte dela, mas os arquivos .CONFIG são editados apenas por desenvolvedores e profissionais de suporte.

4) Mesmo que seja criada uma interface para a edição das permissões nos arquivos .CONFIG, fazer isso em uma aplicação em produção não é bom. A edição dos arquivos .CONFIG gera diversas consequencias na aplicação, como perdas de sessão e recompilações.

5) O permissionamento de objetos dentro de uma página é feito por código, então a ligação de um grupo com as permissões que o grupo tem fica codificada, dificultando muito a manutenção.

Inicialmente poderíamos imaginar que bastaria apenas trocar o local de armazenagem das informações de autorização para resolver a grande maioria dos problemas. Realmente resolveria, o problema é que esta troca não é tão simples : Não existem providers para autorização, o sistema de autorização é nativo e rígido, ao contrário do que acontece com a autenticação.

Authorization Manager

Como alternativa a MS tem o AzMan - Authorization Manager - um novo recurso incluido no Windows 2003 Server para resolver problemas de autorização. Resolve, para intranets. O AzMan é integrado ao Active Directory, apenas reconhece usuários do AD.

Isso é realmente uma grande lástima, pois o AzMan faz bem a parte de autorização. As informações de autorização podem estar no AD ou em arquivos XML. Define-se uma aplicação, tarefas a serem permissionadas, agrupa-se as tarefas e liga-se os grupos de tarefas aos grupos de usuários, bem legal, especialmente considerando-se que quando inserido no AD não usa a estrutura de grupos do domínio, para não bagunçar a casa do pessoal de Infra, cria uma estrutura a parte.

Mas só reconhece usuários do AD, o que é uma verdadeira lástima. Se aceitasse receber uma string com o nome de usuário, vincula-lo aos grupos e identificar suas permissões seria muito legal, mas limitando-se a usuários do AD fica preso apenas para intranets.

O ASP.NET 2 tentou um casamento com o AzMan através do Role Manager, que tem um provider para ele - AuthorizationStoreRoleProvider - mas o Role Manager fecha-se em sua interface para identificar se o usuário está ou não dentro de um grupo e não abre os recursos adicionais do AzMan, como por exemplo dado um usuário e uma tarefa descobrir se ele pode executar aquela tarefa. Para essas coisas mais avançadas torna-se necessário ir diretamente nas APIs do AzMan - que tem Interop - o que gera mais código. Alguém até poderia criar algumas classes e custom controls para simplificar a tarefa.

O que o AzMan traz de melhor em relação a autorização nativa é primeiramente a possibilidade de organizar as permissões de forma mais adequada ao invés de dependermos apenas dos grupos de usuários. Além disso o AzMan armazena as informações de autorização de forma isolada da aplicação, assim sendo a edição de tais informações não afeta o funcionamento da aplicação, como aconteceria com os arquivos .CONFIG. Também já traz uma interface de edição das informações de autorização.

Enterprise Library

Mas como o AzMan só funciona em ambiente integrado, surge então a necessidade de criar um sistema de autorização personalizado, que seja mais flexivel. Aqui então devemos ter o cuidado para não cair em um erro comum : O sistema de autorização precisa ser personalizado e só ele. Não precisamos personalizar o sistema de autenticação, nem a armazenagem de usuários (MemberShip) nem de grupo (Role Management), pois estes já funcionam bem.

Mesmo o debate se precisamos ou não criar providers de Membership e Role Management personalizados não é para este momento. A necessidade de ter uma autorização personalizada não implica em termos memberShip e Role Management personalizados, são assuntos diferentes.

Outro equivoco comum é simplesmente criar a base para armazenar os dados de autorização e deixar a cargo do programador da interface o trabalho de consulta-la. Isso aumenta exponencialmente o trabalho de desenvolvimento da interface e prejudica a manutenção do sistema.

O ideal é aplicar o pattern de providers para a autorização, permitindo posteriormente que o sistema de autorização seja personalizado da forma como desejarmos.

Foi pensando nisso que a equipe de patterns & practices criou um provider model para o sistema de autorização. Esse provider model pode ser baixado do site da Microsoft, incluindo os seus fontes, isso faz parte da Enterprise Library.

Esse provider model traz dois providers já disponíveis : Um para manter os dados de autorização em arquivos .CONFIG - o que é exatamente o que não desejamos - outro para manter os dados de autorização no Authorization Manager (AzMan), que não serve a nossos propósitos como já observamos.

Longe de desistir, a Enterprise Library nos abre o caminho, precisamos continuar por esta trilha : Criar um provider que se encaixe no provider model da enterprise library e permita a armazenagem das informações de autorização em banco de dados.

Felizmente já fizeram isso. Vermeer Craig publicou em seu blog um provider para este modelo da enterprise library e que mantém os dados de autorização em base de dados. Vejam em http://midwestcoders.net/blogs/craig_vermeer/archive/2005/06/06/33.aspx

Então temos tudo, o provider model e o provider. Na verdade, não é bem assim. Analisando o provider criado pelo Vermeer, descobrimos problemas na estrutura da base de dados.

A base de dados deste provider é formada por uma única tabela. Esta única tabela tem o nome do que se deseja autorizar e as regras de acesso, definindo quais grupos de usuários podem ter acesso a esse elemento.

Pode ser que para muitos casos esse provider seja adequado e nada mais precise ser feito. Mas para aplicações mais complexas isso não será suficiente. Basta imaginarmos cenários em que o permissionamente desça ao nível de objetos de tela. Quantos nomes de elementos permissionáveis teremos cadastrados ?

Nesta situação, se surge um novo grupo de usuários (por exemplo, foi criado um novo departamento), permissionar este grupo de usuários vira uma tarefa insuportável, pois o volume de elementos que terão que ser atribuidos ou negados ao grupo de usuários é muito grande e a pessoa que estiver fazendo isso nem ao menos lembrará o significado de todos.

Desta forma o ideal é que o modelo de dados de autorização permita que os elementos autorizáveis - aqueles aos quais o usuário pode ganhar ou não permissão - sejam organizados em grupos de permissões, gerando uma organização hierárquica. Assim sendo, ligar grupos de usuários com grupos de permissões torna a manutenção da segurança um trabalho viável.

Com tudo isso, temos então um sistema de providers de autorização adequado. Mas esse é, sem dúvida, apenas o primeiro dos desafios para o desenvolvedor de um sistema de autorização.

Como esse novo sistema de autorização não é nativo, gera uma grande necessidade de codificação para incorpora-lo na aplicação, testando a autorização dos objetos. Cabe então a quem desenvolve este sistema de autorização garantir que seu uso seja simples, não impactando no processo de desenvolvimento.

Veja alguns desafios desta tarefa :

1) Controlar a autorização por página

Cada página precisa checar se o usuário tem permissão para acessa-la ou não. Normalmente esta tarefa seria por demais trabalhosa, mas podemos utilizar o truque de criar uma classe base. Criando uma classe base e fazendo as páginas herdarem desta classe base podemos implementar a checagem de autorização na classe base. Com isso a checagem de autorização será "automática", sem que o desenvolvedor precise interferir.

2) Controlar a autorização dos objetos da página

Eis ai um problema que não é tão simples de resolver. Vamos imaginar o ambiente ideal para o trabalho com autorização. Os webControls poderiam possuir uma propriedade na qual o programador pudesse indicar qual a permissão o usuário precisa possuir para utilizar este webControl. De fato, cada webControl deve estar ligado não a uma, mas a várias permissões. Nos casos mais simples precisariamos de duas permissões, uma para determinar se o webControl estará visivel (visible) outra para determinar se estará habilitado (enabled). Dependendo do webControl, poderiam haver outras possibilidades.

Isso pode ser feito criando um control extender ou um webcontrol sem interface visual. Em qualquer dos dois casos o controle precisará ter uma interface rica em design time e será o responsável pela efetivação da autorização.

Por fim, ainda temos alguns desafios a serem vencidos. Primeiramente, precisamos de uma interface para editar as regras de autorização. Veermer chegou a fazer uma para a versão 2003 de seu provider, mas não para a versão 2005. Se considerar que ainda terá que personalizar o modelo de dados, então é uma completamente nova que precisará ser construida.

Como último passo precisamos garantir que os demais recursos do ASP.NET possam se integrar com o novo sistema de autorização. Como não é um recurso de autorização nativo, alguns recursos não estão preparados para isso.

O caso mais óbvio é o uso de siteMaps. Os siteMaps se integram com a autorização para que os elementos do mapa do site ( itens de menus, treeviews, etc) possam ser exibidos apenas a quem tenha permissão.

Os providers de siteMap estão diretamente interligados com o sistema de autorização nativo. Entãoo para mantermos os mesmos recursos de siteMap precisamos criar um provider personalizado que faça a checagem de autorização no novo modelo de autorização que implantarmos.

Conclusão

Temos no .NET 2 uma arquitetura de autenticação pronta e personalizável, mas precisamos ter um pouco mais de trabalho com a autorização. Mesmo assim é preferível criar uma autorização que se encaixe com os demais recursos existentes do que tentar criar tudo novamente do zero.

 



Dicas para quem está começando:
Veja os próximos eventos
que você não pode perder :

10/1/2009 Bufalo Cast: Windows Azure - Visao Geral
on-line - RJ
Por : devASPNet


17/1/2009 Bufalo Cast: SQL Server Data Services - Storage no Azure
on-line - RJ
Por : devASPNet


24/1/2009 BufaloCast: Visual Studio 2010: As novidades para o desenvolvimento de softwares
on-line - RJ
Por : devASPNet


31/1/2009 BufaloCast: Dublin: O novo host do Workflow Foundation
on-line - RJ
Por : devASPNet


13/12/2009 BufaloCast : SQL Server 2008 Energy Community Launch
on-line - RJ
Por : devASPNet

Leituras imperdíveis para quem está começando:

º Otimizando a performance no ASP.NET::..
º Criando objetos de paginação personalizados na grid::..
º Uma cesta de compras em ASP.NET::..
º Utilizando o Refresh de parâmetros no .NET::..
º ASP.NET FORMS Authentication::..
º Utilizando propriedades dinâmicas no .NET::..
º Corrigindo problemas de deleção em grid com paginação::..
º Cuidado com os componentes de validação::..
º Otimizando o InitializeComponent::..
º Movendo fonte de aplicações entre máquinas::..
º Agilizando a performance da IDE do VS.NET::..
º Utilizando Short Circuit no VB.NET::..


























  Parceiros:
20% de desconto para os membros do grupo na aquisição de livros e inscrição para eventos

Receba dicas de programação e programação .NET:
E-mail:
Incluir Excluir