Article Details                  
 
Programação em Asp.Net - parte X

Abordagem à construção de providers de Mebership customizados

Programação em Asp.Net - parte X


Autor: Luís Abreu

Conteúdo: Introdução à programação em Asp.Net 2.0

Ferramentas: Visual Web Developer February CTP


Durante os últimos dois artigos apresentámos várias novidades relacionadas com a segurança na nova versão da plataforma Asp.net. Como vimos, a nova plataforma apresenta várias funcionalidades interessantes no capítulo da segurança. Para além da nova API (conhecida por Membership API),a nova plataforma introduz também um conjunto novo de controlos que simplificam a realização das principais operações possíveis nesta área (como vimos no último artigo, os controlos cobrem praticamente todas as operações relacionadas com utilizadores, permitindo-nos criar utilizadores, efectuar validação de utilizadores, etc.). Hoje vamos concluir a nossa análise a esta nova API com a criação de um provider de Membership personalizado.


Como construir um provider de Membership personalizado


Todos os providers de Membership existentes possuem um base comum, ou seja, todos os providers têm de herdar da classe MembershipProvider. Esta classe abstracta é responsável por definir um conjunto de métodos que devem ser implementados pelos providers de Membership. Para além de possuir vários métodos abstractos, a classe possui ainda algums métodos internos e/ou protegidos que podem ser utilizados pelas classes derivadas para a realização de várias operações. Por exemplo, a classe MembershipProvider possui um método designado de EncodePassword que pode ser utilizado para proceder ao encoding de uma palavra chave por parte das classes derivadas. Os principais membro desta classe são:



  • ChangePassword: este método é utilizado para efectuar a mudança de uma palavra chave de um utilizador;

  • ChangePasswordQuestionAndAnswer: tal como o próprio nome indica, o principal objectivo deste método é modificar a pergunta e respectiva resposta de recuperação. Este método necessita dos dados do utilizador (nome de utilizador e palavra chave) para ser executado com sucesso;

  • CreateUser: método utilizado para criar uma nova conta de utilizador;

  • DeleteUser: permite efectuar a operação inversa da anterior(ou seja, deve ser utilizado para efectuar a eliminação de uma conta de utilizador);

  • FindUsersByEmail/Name: estes dois métodos permite obter um conjunto de contas de utilizador tendo em atenção o nome de utilizador ou um endereço de e-mail.Convém ainda referir que estes métodos devem estar preparados para suportar paginação das contas de utilizador devolvidas;

  • GetAllUsers: utilizado para obter todas as contas de utilizador existentes (tal como acontecia com o método anterior, é necessário construir este método por forma a suportar a paginação);

  • GetNumberOfUsersOnline: a implementação deste método deverá possibilitar obter o número de utilizadores online na altura em que o pedido foi efectuado;

  • GetPassword: método utilizado para recuperar a palavra chave de um utilizador;

  • GetUser: este método possui dois overloads. O primeiro recebe um object (que deve ser utilizado para passarmos o identificador único de cada utilizador) e um booleano (utilizado para indicar se o utilizador está ou não online); por outro lado, o segundo overload recebe o nome de utilizador e o mesmo parâmetro booleano (passado ao primeiro método). Ambos os métodos deve devolver uma instância do tipo MembershipUser (ou de um tipo derivado) devidamente preenchido caso o utilizador seja encontrado;

  • GetUserNameByEmail: O nome do método diz tudo: permite-nos obter o nome de utilizador associado à conta de email indicada;

  • ResetPassword: método que permite efectuar o reset da palavra chave de um utilizador;

  • UnlockUser: uma novidade pós-beta 1. Este método pode ser utilizado para desbloquear uma conta de utilizador. O bloqueio de uma conta é uma nova funcionalidade que permite bloquear uma conta de utilizador após n falhas na introdução da combinação nome de utilizador/palavra chave;

  • UpdateUser: método utilizado para actualizar os dados de uma determinada conta de utilizador;

  • ValidateUser: este método será com certeza o mais utilizado. Ao receber um nome de utilizador e uma palavra chave deve indicar se a combinação introduzida é ou não válida.


Para além dos métodos, existem ainda algumas propriedades interessantes:



  • ApplicationName: utilizado para obter o nome da aplicação sobre a qual o provider está a trabalhar;

  • EnablePasswordReset: utilizado para indicar se é ou não possível efectuar o reset de palavras chave;

  • EnablePasswordRetrieval: indica se é ou não permitida a recuperação de palavras chave;

  • PasswordAttemptThreshold: define o número de palavras chave erradas que podem ser introduzidas até que conta seja bloqueada;

  • PasswordAttemptWindow: permite definir o tempo até que a contagem de palavras chave erradas seja reiniciada. Por outras palavras, é utilizado para definir o espaço de tempo em que a contagem das palavras chave erradas deve ser efectuada. Ao atingirmos o tempo definido, o valor das tentativas falhadas volta a zero.

  • PasswordFormat: utilizado para definir o formato de armazenamento das palavras chave das contas de utilizador;

  • RequiresQuestionAndAnswer: propriedade que indica se a criação de uma conta de utilizador deve ou não possui um par pergunta/resposta de recuperação;

  • RequiresUniqueEmail: tal como o próprio nome indica, esta propriedade indica se uma conta de email pode estar associada a mais do que uma conta de utilizador.


Convém salientar que a maior parte destas propriedades obtém o valor a partir de valores definidos no ficheiro de configuração.


Obtenção de dados a partir do ficheiro de configuração


Como vimos nos artigos anteriores, alguns dos dados utilizados pela Membership API são definidos através de atributos introduzidos na secção de configuração Membership do web.config. Do ponto de vista do programador, coloca-se uma questão: como é que obtenho essa informação a partir da minha classe Membership? A resposta reside no override do método Initialize herdado indirectamente da classe ProviderBase (esta classe é utilizada como base da classe MembershipProvider).


A classe ProviderBase é uma classe auxiliar que serve de base a todos os providers existentes na plataforma (como veremos nos próximos artigos, existem outros tipos de providers na nova plataforma). Esta classe possui apenas um método virtual (Initialize) que recebe como parâmetros os valores contidos no ficheiro de configuração. O sample que acompanha este artigo efectua o override deste método para obter dados provenientes do ficheiro de compilação.


Para além dos dados "tradicionais" podemos definir novos atributos específicos do provider em questão. A interpretação desses dados será da responsabilidade desse provider (e, como vimos, deverá ser efectuada através do override do método Initialize).


Definição do provider


Após construirmos o nosso provider tempos de modificar o ficheiro web.config por forma a que o nosso provider passe a ser utilizado sempre que haja uma invocação de um método da Membership API. A definição de um novo provider implica a criação de uma nova entrada na secção providers através do elemento <add>. O excerto seguinte foi retirado do código que acompanha este sample:



<membership defaultProvider="LAMembershipProvider">
<providers>
<add name="LAMembershipProvider"
type="LAControls.Providers.LAMembershipProvider"
description="Provider personalizado que demonstra a construção de um provider"
connectionStringName="LADatabase"
enablePasswordRetrieval="true"
enablePasswordReset="false"
applicationName="/"
requiresQuestionAndAnswer="false"
/>
</providers>
</membership>

Como é possível verificar, todos os novos providers devem ser definidos no ficheiro web.config. Todos os providers devem possuir um nome (neste caso, o provider chama-se LAMembershipProvider). O nome é importante para definirmos o provider utilizado na aplicação (note-se que a definição do provider utilizado pela aplicação web é feita através da propriedade defaultProvider do elemento membership.


Detalhes de implementação


A construção de um MembershipProvider é simples devido ao padrão de desenho utilizado. Em vez de gastar espaço com o código relativo ao provider, vou redireccionar o leitor para o código que acompanha o artigo por forma a obter mais detalhes sobre a implementação deste tipo de elementos. Ao contrário do que acontecerá na vida "real", o provider construído é muito simples pois implementa apenas os métodos essencias (como por exemplo, a validação de utilizadores). Todos os métodos não implementados geram uma excepção do tipo NotImplementedException.


Para utilizarem o código têm de configurar o serviço de email do IIS ou, alternativamente, utilizarem um servidor de email que possa ser utilizado com as classes de envio de email (parece-me que o meu servidor de email - ou melhor, o servidor de email do meu provider - não é "compatível" com as classes de envio de mail fornecidas pela framework; devido a isso tive de configurar o servidor de email do IIS por forma a que este enviasse os mails para o meu servidor. Existe um Kb interessante que explica como configurar essa funcionalidade).


Quando construir um provider personalizado


Após analisar o modelo de providers, cheguei à conclusão que o modelo adequa-se a cerca de 90% das situações do mundo real. Na maior parte das situalções o programador limitar-se-á a utilizar um dos providers existentes. Contudo, existem casos em que a existência de dados num formato diferente do suportado pela plataforma impedem a utilização directa dos providers existentes. Nestas situações podemos simplesmente construir o nosso próprio provider e adicioná-lo à aplicação.


Outra situação que pode levar à construção de um provider específico reside no facto dos dados associados à conta de utilizadores ficarem armazenados numa base de dados para a qual não existe ainda providers construídos.


Conclusões finais


Ao longo dos últimos três artigos apresentámos as principais características do novo modelo de segurança associado à nova plataforma Asp.Net. A nova plataforma apresenta uma nova API que simplifica as operações associadas à criação, modificação, eliminação e validação das contas de utilizadores. Para além da nova API, a nova versão do Asp.Net apresenta ainda um conjunto de controlos que simplica a utilização da nova API. Como vimos ao longo da série, a nova API é construída de acordo com o padrão dos providers que permite a fácil extensão e criação de novos providers personalizados.


No próximo artigo vamos continuar a falar de segurança e vamos apresentar a nova API que permite trabalhar com roles. Ao longo desse artigo vamos começar por introduzir o conceito e estudarmos o suporte fornecido pela framework para a utilização desta nova funcionalidade,


O código que acompanha este artigo irá ser disponibilizado na secção de downloads do site (está a aguardar autorização). Por favor enviem-me as vossas opiniões/sugestões/críticas/correcções para progC@netmadeira.com.


Fiquem bem e boa programação! Até à próxima.


Leiam o meu blog em: http://weblogs.pontonetpt.com/luisabreu


Written By: labreu
Date Posted: 4/14/2006
Number of Views: 649

Return