Desenvolvimento - ASP. NET

Segurança - ASP.NET 2.0 - Utilizando Providers Models

Ao contrário do ASP.NET 1.x, o ASP.NET 2.0 nos fornece uma grande infraestrutura, incluindo classes e controles, para trabalharmos com segurança e gerencimento de usuários das nossas aplicações Web.

por Israel Aéce



Ao contrário do ASP.NET 1.x, o ASP.NET 2.0 nos fornece uma grande infraestrutura, incluindo classes e controles, para trabalharmos com segurança e gerencimento de usuários das nossas aplicações Web. Nas versões anteriores, tínhamos que construir nossas próprias classes para gerir os usuários da nossa aplicação em nossa Base de Dados ou mesmo no Active Directory e, sendo assim, tínhamos que escrever muito mais códigos para atingirmos este nosso objetivo, isso ainda sem levar em consideração a parte de designer (ASPX).

Na versão 2.0 do ASP.NET, com a grande gama de controles a nosso dispor para melhor trabalharmos o front-end (UI), temos ainda classes para manipular os usuários em nossa Base de Dados. Classes que utilizam o Provider Model Design Pattern, e assim conseguímos ter um código genérico, independentemente de que Banco de Dados (ou qualquer outro tipo de repositório) estamos utilizando em nossa aplicação.

A Infraestrutura

Assim como o Profile, o ASP.NET também utiliza o Providers para gerenciar a segurança, sendo eles, dois providers: MembershipProvider e o RoleProvider. O MembershipProvider é utilizado para gerir os usuários (armazenando, criando, excluindo e alterando) e passwords. O RoleProvider é utilizado para gerenciar as Roles (Regras) dos usuários dentro da aplicação.

Para versão Beta 1, o Provider padrão é o AccessMembershipProvider. Como o Microsoft Access não suporta um grande volume de usuários "pendurados", ele foi substituído pelo SqlMembershipProvider na versão Beta 2 do Visual Studio .NET 2005, e como o próprio nome diz, é voltado para o Banco de Dados SQL Server. Se ainda há alguém que pretende utilizar o AccessMembershipProvider, é possível encontrá-lo neste endereço.

Os dois providers são descendentes de uma mesma classe abstrata, chamada MemberShipProvider, deixando assim, flexível para extender a funcionalidade para outros tipos de Banco de Dados, como por exemplo Oracle, Sybase, ou até mesmo arquivos XML, bastando apenas herdar da classe base, MemberShipProvider, e implementar os métodos e propriedades para a Base de Dados que deseja utilizar.

Para utilizar o SqlMembershipProvider, é necessário termos dentro do SQL Server os objetos (Tabelas e Stored Procedures) necessários para que seja possível o uso deste Provider. Junto ao Microsoft .NET que é instalado na máquina, existe uma ferramenta chamada "aspnet_regsql.exe", que faz todo este processo automaticamente, onde apenas precisamos informar o servidor e o Banco de Dados onde serão instalados estes objetos.

Depois do provider escolhido, ainda é necessário definirmos no arquivo Web.Config qual será o provider a ser utilizado. Abaixo um exemplo de como definí-lo:

1
2
3
4
5
<configuration>
<system.web>
<membership defaultProvider="AspNetSqlProvider" />
</system.web>
</configuration>

Código 1 - Definindo a estrutura do Provider de segurança no arquivo Web.Config.


Como vemos, no atributo defaultProvider definimos o nome do provider que utilizaremos na aplicação. Este provider está definido dentro da coleção de providers, podemos também definir dentro do arquivo de configuração (Machine.Config ou Web.Config) os providers que podemos ou não utilizar.

Quando criamos o nosso próprio provider, precisamos registrá-lo na coleção de providers e assim, definimos uma séria de atributos, sendo um deles o type, que informará a classe que será utilizada. Nada impedirá de ter mais de um provider definido, mas obrigatoriamente, no atributo defaultProvider, devemos especificar o provider que iremos utilizar na aplicação. Abaixo temos uma lista completa:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<configuration>
<system.web>
<membership defaultProvider="AspNetSqlProvider">
<providers>
<add name="AspNetSqlProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="Connection_String"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
passwordFormat="Hashed"
applicationName="/" />
</providers>
</membership>
</system.web>
</configuration>

Código 2 - Configurando os providers.


Atributo Descrição
name Nome do Provider.
type Tipo do objeto, incluindo o Namespace.
connectionStringName Connection String com a Base de Dados.
enablePasswordRetrieval Possibilita ou não recuperar o password de um usuário.
enablePasswordReset Possibilita ou não que usuários possam reiniciar seu password com um outro aleatório.
requiresQuestionAndAnswer Indica se o usuário deverá ou não responder a questão antes de recuperar ou reiniciar o seu password.
passwordFormat Opções: Clear, Encrypted e Hashed.
applicationName Nome da Aplicação. Utilizado quando você precisa isolar os usuários em aplicações diferentes, utilizando esta mesma estrutura.

Nota: É importante mencionar que dentro do .NET Framework, também já temos implementada a classe ActiveDirectoryMembershipProvider, que faz o mesmo trabalho, mas agora, utilizando o Active Directory como repositório.

Os Controles

O ASP.NET 2.0 contém um conjunto completo de controles para trabalharmos com a segurança, contendo inclusive uma Tab chamada Security dentro da ToolBox do Visual Studio .NET 2005 para armazenar estes controles. Vamos neste artigo, analisar superficialmente alguns destes novos controles, como por exemplo o ChangePassword, CreateUser, LogIn, LoginView e o PasswordRecovery. Estes controles também tem a grande vantagem de trabalharem diretamente com o Provider que definimos no arquivo Web.Config, e assim, fazem todo o processo, inclusive as queries necessárias para manipular os dados na Base de Dados.

ChangePassword

Figura 1 - Controle que permite a mudança de password.

O controle ChangePassword tem a finalidade de alterar o password de um determinado usuário, onde temos propriedades para configurar, como por exemplo a propriedade MailDefinition que permite a você definir um email para quando o usuário alterar o password, de forma que uma mensagem é enviada a ele informando a mudança e o seu novo password.

CreateUser

Figura 2 - Controle que permite a criação de novos usuários.

Este controle, do tipo Wizard, permite a criação de novos usuários dentro na Base de Dados, permitindo também o envio de um email de confirmação ao usuário que foi cadastrado. Este controle também possui uma propriedade chamada AutoGeneratePassword, que é responsável por gerar um password randômico para o novo usuário.

LogIn

Figura 3 - Controle para efetuar o Login.

Como podemos perceber, este controle, dado um nome de usuário e password, possibilita-nos a verificar se um determinado usuário encontra-se ou não cadastrado em nossa Base de Dados. Temos também uma propriedade interessante neste controle, chamada VisibleWhenLoggedIn, esta por sua vez, recebe um valor booleano, indicando se este controle será visível ou não quando o usuário já estiver logado na aplicação.

LoginView

Figura 4 - Controle LoginView.

Particularmente um dos controles mais interessantes. Ele exibe vários templates para diferentes situações (chamamos isso de ContentTemplate), dependendo de Roles de usuários e também tendo opção para definirmos o que vamos exibir quando o usuário ainda não está autenticado em nossa aplicação. Um cenário bastante utilizado, é quando temos áreas dentro da nossa aplicação, onde este conteúdo varia de acordo com o tipo de usuário, ou seja, quando o usuário é do tipo "Gerente", exibe os valores das operações. Já quando o usuário é do tipo "Operador", a quantidade de pendências é exibida.

Outro cenário muito comum, é quando o usuário ainda não encontra-se autenticado, e assim exibimos a seguinte mensagem: "Seja bem vindo ao nosso site.". Quando o usuário se identifica, efetuando o Login, passamos a exibir uma mensagem mais customizada: "Olá José, seja bem vindo.".

PasswordRecovery

Figura 4 - Controle PasswordRecovery.

Finalmente o controle PasswordRecovery. Este controle é responsável por enviar o password ao usuário. Mas isso terá um comportamento diferente, dependendo de algumas opções que definimos na configuração do provider. Se o atributo enablePasswordRetrieval estiver definido como True e o atributo passwordFormat não for Hashed, então o password do usuário é enviado em "clean text" para o usuário, caso contrário, é gerado automaticamente um novo password aleatório e posteriormente enviado ao respectivo usuário.

A classe Membership

Como já vimos anterioramente, está é uma classe abstrata, contendo uma série de métodos compartilhados. Esta classe recebe em runtime a instância da classe concreta, ou seja, do provider que definimos o arquivo Web.Config. Claro que estes métodos serão invocados da classe concreta, pois é onde se encontram os métodos implementados para uma Base de Dados específica.

Abaixo é exibido uma lista com os principais métodos desta classe:

Membro Descrição
Public MethodShared CreateUser Cria um novo usuário.
Public MethodShared DeleteUser Exclui um usuário.
Public MethodShared FindUsersByEmail Resgata os usuários baseando-se em um endereço de email.
Public MethodShared FindUsersByName Resgata os usuários baseando-se em um userName.
Public MethodShared GeneratePassword Gera um password aleatório.
Public MethodShared GetAllUsers Retorna todos os usuários.
Public MethodShared GetNumberOfUsersOnline Retorna um número inteiro representando todos os usuários online.
Public MethodShared GetUser Resgata um determinado usuário baseando-se em um userName.
Public MethodShared GetUsernameByEmail Resgata um determinado usuário baseando-se em um endereço de email.
Public MethodShared UpdateUser Atualiza as informações de um determinado usuário.
Public MethodShared ValidateUser Retorna um valor booleano indicando se o usuário existe ou não.

Para utilizar esta API, não há a necessidade de criar a sua instância, por motivos que já vimos acima. Basta apenas chamar os métodos compartilhados da classe Membership e já estará usufruindo de todo o Membership, e também, já refletindo as alterações na Base de Dados. Abaixo alguns exemplos:

1
2
3
4
5
"Criando usuário
Membership.CreateUser("IsraelAece", "123456")
"Excluindo usuário
Membership.DeleteUser("IsraelAece")

Código 3 - Utilizando o Provider na aplicação.

CONCLUSÃO: Os Providers Models vieram na hora certa, onde agora, podemos trabalhar mais facilmente com código genérico, deixando assim a aplicação bastante flexível. Já que contamos com este design também na parte de segurança do ASP.NET, isso evitará escrevermos muitos códigos, assim como fazíamos nas versões anteriores. Estas funcionalidades já encontram-se encapsuladas dentro dos Providers e controles disponibilizados para a nossa utilização.

Artigo desenvolvido utilizando:

* Visual Studio .NET 2005 - Beta 2
* .NET Framework 2.0
* Windows XP Professional - SP2

Israel Aéce

Israel Aéce - Especialista em tecnologias de desenvolvimento Microsoft, atua como desenvolvedor de aplicações para o mercado financeiro utilizando a plataforma .NET. Como instrutor Microsoft, leciona sobre o desenvolvimento de aplicações .NET. É palestrante em diversos eventos Microsoft no Brasil e autor de diversos artigos que podem ser lidos a partir de seu site http://www.israelaece.com/. Possui as seguintes credenciais: MVP (Connected System Developer), MCP, MCAD, MCTS (Web, Windows, Distributed, ASP.NET 3.5, ADO.NET 3.5, Windows Forms 3.5 e WCF), MCPD (Web, Windows, Enterprise, ASP.NET 3.5 e Windows 3.5) e MCT.