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. Estes controles estão fortemente integrados com o Membership, e fornecem uma porção de funcionalidades que são utilizadas comumente dentro de uma aplicação Web, como por exemplo: alteração de senhas, recuperação de senhas, criação de usuários, etc. A imagem abaixo mostra os controles disponíveis dentro do Visual Studio .NET 2005, e analisaremos cada um deles mais abaixo:
|
Figura 1 – Controles de segurança do Visual Studio .NET 2005. |
Login
O controle Login é um Composite Control, ou seja, ele é composto por vários outros controles que fazem o trabalho de validação do usuário. Entre esses controles podemos citar TextBoxes, controles de validação (RequiredFieldValidator) e um Button. Os controles RequiredFieldValidators, junto com os demais controles, são devidamente agrupados para que os mesmos não interfiram nos possíveis seções que temos na página onde ele estará hospedado. Esses validadores são necessários para evitar que o usuário submeta o formulário sem informar o Login e Senha. Fora isso, este mesmo controle ainda permite uma série de outros recursos, os quais veremos mais adiante.
Este controle usa o Membership Provider para validar o usuário na fonte de dados especificada no arquivo Web.Config. É importante dizer que este controle utiliza o provider e, se desejar que esse seu controle trabalhe com um outro provider, pode especificá-lo na propriedade MembershipProvider do mesmo. Para nos certificarmos disso podemos recorrer à ferramenta .NET Reflector e visualizar o método interno chamado AuthenticateUsingMembershipProvider da classe Login. Repare que ele recupera o provider do arquivo Web.Config e, através do método ValidateUser, valida o usuário junto a fonte de dados:
private void AuthenticateUsingMembershipProvider(AuthenticateEventArgs e) { MembershipProvider provider1 = LoginUtil.GetProvider(this.MembershipProvider); e.Authenticated = provider1.ValidateUser(this.UserNameInternal, this.PasswordInternal); } |
O controle Login ainda fornece um evento que permite-nos interceptar e customizar a autenticação do usuário dentro da aplicação. Isso é possível graças ao evento chamado Authenticate, o qual tem em sua assinatura um argumento do tipo AuthenticateEventArgs. Este argumento provê uma propriedade booleana chamada Authenticated, qual indicará ao provider se já autenticamos o usuário. Um exemplo disso é mostrado abaixo:
private void OnAuthenticate(object sender, AuthenticateEventArgs e) { e.Authenticated = ValidacaoCustomizada(Login1.UserName, Login1.Password); } |
Ainda existem mais dois eventos que merecem algum comentário: LoggingIn e LoggedIn. O primeiro deles ocorre quando o usuário submete os dados para validação junto ao provider. Em outras palavras, ocorre quando o usuário pressiona o botão do controle Login. Esse evento manda em sua assinatura um argumento do tipo LoginCancelEventArgs, o qual contém uma propriedade chamada Cancel, onde você pode, em um último momento, evitar que a autenticação seja feita. Já o LoggedIn ocorre quando, as credenciais do usuário já foram validadas pelo provider e o cookie já foi criado e enfileirado para ser enviado ao browser na próxima resposta. A ordem de disparo destes eventos são: LoggingIn, Authenticate e por fim LoggedIn. Ainda temos algumas propriedades interessantes no controle Login, as quais poderemos visualizar abaixo:
|
LoginView
Este controle tem uma característica interessante: ele exibe um template para customizarmos um conteúdo para um determinado status ou role em que o usuário se encontra em um determinado momento. Dentro dele temos alguns templates, os quais merecem uma explicação:
-
AnonymousTemplate: especifica um template para usuários que não estão logados na aplicação, e usuários logados nunca visualizarão este template.
-
LoggedInTemplate: especifica um template padrão para usuários que estão logados na aplicação mas não contidos em qualquer role que tenha um template próprio.
-
RoleGroups: especifica um template para usuários que estão logados na aplicação, porém podemos ter aqui templates para determinadas roles e, conseqüentemente, somente usuários contidos naquela role poderão visualizar. Este controle mantém uma propriedade chamada RoleGroups do tipo RoleGroupCollection, onde podemos/devemos definir as roles através de objetos do tipo RoleGroup.
Abaixo é mostrado um exemplo de como estar utilizando o controle LoginView:
<asp:LoginView id="LoginView1" runat="server"> <AnonymousTemplate> É necessário logar na aplicação. </AnonymousTemplate> <LoggedInTemplate> Seja bem vindo <asp:LoginName id="LoginName1" runat="Server" />. </LoggedInTemplate> <RoleGroups> <asp:RoleGroup Roles="Admin"> <ContentTemplate> Sr(a). Administrador, <asp:LoginName id="LoginName2" runat="Server" /> </ContentTemplate> </asp:RoleGroup> </RoleGroups> </asp:LoginView> |
PasswordRecovery
Este controle tem a finalidade de recuperar a senha de um determinado usuário. É um controle composto por TextBox, RequiredFieldValidator e um Button onde, dado um username, o provider busca na fonte de dados e o devolve. Essa devolução é realizada através de envio de e-mail para o endereço cadastrado previamente.
Para que a senha possa ser recuperada o seu provider não pode estar configurado para salvar a mesma como Hashed pois, como sabemos, é um algoritmo que não é possível reversão e, além disso, a propriedade EnablePasswordRetrieval do Membership deve estar definida como True. Se por acaso a forma de armazenamento da senha estiver como Hashed, gera então uma nova senha e envia esta para o usuário.
Agora somente nos resta configurar o e-mail para enviar ao usuário. Para isso, utilizaremos o elemento mailSettings no arquivo Web.Config. Abaixo é exibido um exemplo de como proceder nas configurações:
<system.net> <mailSettings> <smtp deliveryMethod="Network"> <network host="mail.site.com.br" port="25" /> </smtp> </mailSettings> </system.net> |
<asp:PasswordRecovery id="PasswordRecovery1" runat="server"> <successtemplate> <table border="0" style="font-size:10pt;"> <tr> <td>A senha foi enviada para o seu e-mail.</td> </tr> </table> </successtemplate> <mailDefinition From="atendimento@site.com.br Subject="Nova Senha" BodyFileName="RecuperacaoSenha.txt" /> </asp:PasswordRecovery> |
Olá <% UserName %>, A sua nova senha é <% Password %>. Obrigado! |
UserName e Password são palavras reservadas que, antes de enviar o e-mail, o ASP.NET automaticamente substitui os respectivos dados pelos valores efetivos.
LoginStatus
O controle LoginStatus fornece-nos dois estados: logado e não logado, e o mesmo consegue obter essa informação através da propriedade IsAuthenticated da classe Page. Este controle pode exibir um Link ou uma Imagem (dependendo das propriedades LoginImageUrl e LogoutImageUrl). Quando o usuário não está logado, o controle fornece um link até a página de login da aplicação. Se o usuário estiver logado, este controle fornece um link para a página de logout da aplicação. No caso do Logout internamente ele se encarrega de chamar o método SignOut da classe FormsAuthentication.
Há também um comportamento muito interessante dentro deste controle, que é a propriedade LogoutAction, a qual recebe um enumerador do tipo LogoutAction. Esta propriedade vai dizer ao controle o que ele deve fazer quando o usuário efetuar o logout na aplicação. O enumerador LogoutAction tem três opções, as quais são explicadas abaixo:
-
Redirect: redireciona o usuário para a página especificada na propriedade LogoutPageUrl e, se esta estiver vazia, o usuário é redirecionado para a página de login da aplicação, configurada no arquivo Web.Config.
-
RedirectToLoginPage: redireciona o usuário para a página de login da aplicação, configurada no arquivo Web.Config.
-
Refresh: apenas atualiza a página atual.
LoginName
O controle LoginName apenas exibe o valor contido dentro da propriedade System.Web.UI.Page.User.Identity.Name. Lembrando que, se a propriedade estiver definida com um valor vazio, o controle não é exibido. Uma restrição que há em cima deste controle é que ele não pode ser usado fora da tag form, como por exemplo no title de uma página.
CreateUserWizard
Este controle (CompositeControl) fornece uma interface para a criação de um novo usuário, utilizando a arquitetura do Membership. Como o controle confia no provider informado, ele irá obrigar o usuário a digitar informações como E-mail, Question, Answer. Se a definição da propriedade AutoGeneratePassword estiver definida como True o próprio ASP.NET se encarrega de gerar a senha aleatória e salvá-la na fonte de dados.
O controle CreateUserWizard permite-nos enviar um e-mail automaticamente ao usuário assim que o processo for concluído e, para isso, é necessário a configuração do elemento mailDefinition, bem como o SMTP no arquivo Web.Config. Há ainda algumas propriedades opcionais interessantes:
|
ChangePassword
O controle ChangePassword possibilita ao usuário trocar uma senha por outra que ele desejar. Para que isso aconteça, é disponibilizado neste controle três TextBox, onde temos os seguintes campos a serem preenchidos: senha atual, nova senha e confirmação da nova senha. Este controle também permite a configuração do elemento mailDefinition para o envio da nova senha para o e-mail do usuário.