Pesquisar no Programero

domingo, 8 de março de 2009

Login com segurança baseada em formulários .NET

Olá a todos, esse é o nosso primeiro artigo relacionado ao .NET e confesso que ainda tenho muito a aprender. Como em todo novo processo de aprendizagem realizamos novas descobertas e agora irei compartilhar aqui uma de minhas primeiras.
Quando iniciei meus estudos comecei com a tela inicial de todo sistema (ou quase todos) a tela de login, onde o usuário ganha acesso ao restante das aplicações. Procurando pela net encontrei esse ótimo tutorial do Macoratti, simples e direto que me ajudou muito a construir a minha própria tela de login.
Segue abaixo o tutorial na integra, sem alterações, peço que todos que se utilizarem dele dêem um pulo no site para prestigiá-lo.
ASP.NET - Usando segurança baseada em formulários (por José Carlos Macoratti)
O ASP.NET realiza muitas tarefas que antes , usando ASP, ficavam por conta do programador. O Controle de Login com ASP.NET ficou muito simples de ser realizado.
Vamos então mostrar como ficou o processo de proteger páginas dinâmicas com ASP.NET. Ele não faz tudo sozinho (ainda) temos que fazer algumas configurações e criar algumas páginas mas se você já precisou fazer esta tarefa em ASP vai concordar que agora é mais fácil.
Vou desenhar o cenário onde iremos trabalhar:
Suponha que você tenha uma aplicação Web e que vai precisar proteger algumas páginas da sua aplicação do acesso anônimo. Para tornar o processo compreensível e não poluir o código vou trabalhar com duas páginas:
- Login.aspx - página que irá realizar o login do usuário.
- Login-protegido.aspx - página que desejamos proteger do acesso anônimo. Somente usuários autenticados terão acesso a esta página.
Estas duas páginas estarão no mesmo diretório da aplicação web ; o diretório Login2. Vamos criar então um diretório de trabalho da nossa aplicação web subordinado a inetpub\wwwroot com a seguinte estrutura :

Até agora eu não falei nele mas você notou que na pasta login2 da nossa aplicação existe um arquivo com o nome de web. Pois ele é o personagem principal do nosso artigo. Vamos então falar mais sobre ele.
O arquivo web.config é um arquivo no formato XML que possui informações sobre todo o projeto Web. O elemento-raiz de um Web.config é a tag <configuration> . A princípio o arquivo Web.config não é um arquivo exigido para que a aplicação funcione. Se não houver necessidade de nenhuma configuração especial o arquivo nem precisa existir. Se ele não existir será usado um arquivo chamado Machine.config padrão que possui configurações padrões definidas.
Abaixo temos as configurações possíveis para serem usadas no arquivo Web.config :
Seção
Descrição
<appSettings>
Utilizada para armazenar suas próprias configurações personalizadas de Aplicativo.
<authentication>
Configura como o ASP.NET autentica seus usuários.
<authorization>
Configura a autorização de recursos no ASP.NET.
<browsercaps>
Responsável por controlar as configurações do componente de capacidades do navegador.
<compilation>
Responsável por todas as configurações de compilação.
<customErrors>
Indica como exibir erros no navegador.
<globalization>
Responsável por configurar as opções de globalização.
<httpHandlers>
Responsável pelo mapeamento de URLs de entrada em classes IHttpHandler.
<httpModules>
Responsável por configurar Módulos de HTTP dentro de um aplicativo.
<identity>
Controla como o ASP.NET acessa seus recursos.
<location>
Controla como as configurações se aplicam a um diretório.
<pages>
Controla configurações de páginas.
<processModel>
Configura as configurações de modelo de processo do ASP.NET em Sistemas de Servidor da Web do IIS.
<sessionState>
Configura o Estado de Sessão.
<trace>
Configura o Trace (Rastreamento).
<webServices>
Controla as configurações dos Serviços da Web.
Podemos colocar o arquivo Web.config em qualquer diretório da aplicação Web , mas como geralmente ele contém configurações a nível de site que devem ser válidas a partir do diretório onde ele se encontra e nos demais subdiretórios ele é colocado no diretório raiz da aplicação web.
Nota: Se você receber o erro :
Parser Error Message: It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS. 
ao acessar a aplicação veja como corrigir o problema acessando o site : IIS Insider
Provavelmente seu diretório virtual não foi configurado como uma aplicação no IIS e por isto não esta sendo reconhecido.
Vamos usar então o arquivo Web.config para informar ao ASP.NET que desejamos realizar a autenticação baseada em formulários e quais as páginas que desejamos proteger. Vamos então fornecer as seguintes informações ao Web.config:
- Que desejamos realizar a autenticação baseada em formulários
- Qual a página que desejamos proteger
- Qual será a nossa página de Login
- Quais usuários poderão acessar as páginas.
Se você não nem idéia de como criar um arquivo Web.Config você pode criar uma aplicação ASP.NET no Visual Studio.NET que ele será criado com as configurações padrões. Se você abrir o arquivo Web.config criado assim verá muitas tags por isto eu já vou mostrar a abaixo a estrutura do arquivo Web.Config que estarei usando na aplicação:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>


<!-- habilita a autenticacao -->
<system.web>
  <authentication mode="Forms">
<forms name="Exemplo" loginUrl="login.aspx" />
</authentication>
 </system.web>


<!-- define a pagina protegida para rejeitar usuarios anonimos -->
 <location path="login-protegido.aspx">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
</configuration>


Destacamos o código em cores para facilitar a visualização. Funciona assim:


1- Elemento authentication : Habilitando a autenticação e definindo a página de login


<authentication mode="Forms">

<forms name="Exemplo" loginUrl="login.aspx" />


</authentication>



Na tag <authentication> indicamos o modo Forms que implementa a segurança baseada em formulários.(Existem outros modos)


A seguir  no atributo LoginUrl especificamos qual será a nossa página de Login: login.aspx


2- Elemento authorization : Definindo quem terá acesso a página protegida e a página protegida.


<location path="login-protegido.aspx">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>



<location path="login-protegido.aspx"> define a página que desejamos proteger

<deny users="?" /> -A ? usada no elemento Deny indica que será negado o acesso a usuário não logado ou seja não autenticado.


Vamos agora ao código da página login.aspx :(O destaque em cores diferentes do código HTML e do script VB.NET)


<%@ Page Language="VB" %>
<script runat="server">


Sub btnLogin_OnClick(Src As Object, E As EventArgs)

if txtUsuario.Text = "Macoratti" And txtSenha.Text = "123456"
FormsAuthentication.RedirectFromLoginPage(txtUsuario.Text, True)
        Else
lblInvalido.Text = "Senha/Usuário inválidos... tente novamente..."
End If

End Sub


</script>


<html>
<head>
<title>ASP.NET - Exemplo de Login</title>
</head>
<body>
<h2>Login 
</h2>
<p>
<em>Dica: Usuario = "Macoratti"&nbsp; e&nbsp; Senha =&nbsp;"123456" </em>
</p>
<form runat="Server">
<p>
Usuário: 
<asp:TextBox id="txtUsuario" runat="server" Width="138px"></asp:TextBox>
<br />
Senha&nbsp;&nbsp; : 
<asp:TextBox id="txtSenha" runat="server" Width="137px" TextMode="Password"></asp:TextBox>
<br />
<br />
<asp:Button id="btnLogin" onclick="btnLogin_OnClick" runat="server" text="Login"></asp:Button>
</p>
<p>
A pagina que estamos protegendo é : <a href="login-protegido.aspx">login-protegido.aspx</a>. 
<br />
(Se voce&nbsp;&nbsp;NÃO estiver logado e clicar neste link voltará&nbsp;a esta&nbsp;página.
) 
</p>
<p>
<asp:Label id="lblInvalido" runat="server" font-bold="True" forecolor="Red"></asp:Label>
</p>
</form>
</body>
</html>


O código com destaque na cor amarela é apenas código HTML onde temos dois controles TextBox , um controle Button e uma Label.


No código do script VB.NET na cor cinza a linha mais importante esta destacada :


FormsAuthentication.RedirectFromLoginPage(txtUsuario.Text, True)

Aqui estamos usando a classe FormsAuthenticacion que fornece métodos estáticos (shared) para manipular a autenticação. Esta classe não pode ser herdada.


O método RedirectFromLoginPage redireciona um usuário autenticado de volta a URL original da requisição. Os parâmetros usados no construtor do método usado são :


UserName - Nome do usuário para o cookie de autenticação. Representado aqui por txtUsuario.text.

CookiePersistente - Define se um cookie permanente será criado. Podemos ter dois valores False ou True.


Ao executar o arquivo login.aspx teremos o seguinte :


Se tentarmos acessar a página protegida login-protegido.aspx seremos redirecionados para a página login.aspx


Se o usuário não estiver autenticado quando clicar no botão Login ele retorna a página login.aspx.


Após se autenticar o usuário se autenticar (eu estou usando um usuário fixo no código mas você pode fazer o acesso a um banco de dados para verificar nome e senha) ele terá acesso a página login-protegido.aspx


Abaixo temos as telas que mostram este funcionamento:


Ao tentar a página login-protegido.aspx somos remetidos à página de login : login.aspx





Após fazer a autenticação temos acesso a página protegida : login-protegido.aspx





O código da página login-protegido.aspx é o seguinte :


<%@ Page Language="VB" %>
<script runat="server">


Sub btnLogout_OnClick(Src As Object, E As EventArgs)
FormsAuthentication.SignOut
End Sub


</script>
<html>
<head>
<title>ASP.NET - Exemplo de login</title>
</head>
<body>
<p>
Este é o texto super secreto que somente os visitantes autorizados podem ver : 
</p>
<strong>"Mesmo a mais longa jornada começa com o primeiro passo."</strong> 
<p>
</p>
<form runat="server">
<asp:Button id="btnLogout" onclick="btnLogout_OnClick" runat="server" text="Log Out"></asp:Button>
</form>
<p>
<font color="blue">Nota: Depois de clicar no botão "Log Out" você vai precisar dar um
'Refresh' na página. </font>
</p>
</body>
</html>


O botão Log Out a utiliza aciona o método SignOut da classe FormsAuthenticacion que remove a autenticação realizada.


Para terminar vou deixar aqui o código para uma página de login que utiliza o acesso a um base de dados Access chamada Acesso onde a tabela Usuarios  possui um campo Nome e outro Senha que serão verificados após o usuário preencher o formulário e clicar no botão Login.


<%@ Page Language="VB" %>
<%@ import Namespace="System.Data" %>
<%@ import Namespace="System.Data.OleDb" %>
<%@ import Namespace="System.Web.Security" %>


<script runat="server">


Function ValidaUsuario(nome As string, senha As string) As Boolean


Dim strSQL as string = "Select * from Usuarios Where Nome=@Nome AND Senha=@Senha"


Dim MyConn as New OleDbConnection(ConfigurationSettings.AppSettings("strConn"))
Dim objDR as OleDbDataReader
Dim Cmd as New OleDbCommand(strSQL, MyConn)


cmd.Parameters.Add(New OleDbParameter("@Nome", nome))
cmd.Parameters.Add(New OleDbParameter("@Senha", senha))


Try


MyConn.Open()


objDR=Cmd.ExecuteReader(CommandBehavior.CloseConnection)


if objDR.Read() Then


 FormsAuthentication.RedirectFromLoginPage(objDR("Nome"), False )


else
saida.Visible="True"
saida.text="Usuário/Senha Inválido(s) , tente novamente."


End If


Catch ex as Exception
saida.visible="true"
saida.text="Ocorreu um erro durante o Login : " &  "<p>" & ex.Message()
Finally
MyConn.Close()
End Try


End Function


Sub Login(Source as Object, E as EventArgs)
Validausuario(Nome.Text,Senha.Text)
End Sub


</script>
<html>
<head>
</head>
<body>
<h1>Login
</h1>
<hr />
<form runat="server">
<table cellpadding="8">
<tbody>
<tr>
<td>
Usuário :
</td>
<td>
<asp:TextBox id="Nome" RunAt="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
Senha&nbsp;&nbsp; :
</td>
<td>
<asp:TextBox id="Senha" RunAt="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
</td>
<td>
<p align="center">
<asp:Button id="Button1" onclick="Login" RunAt="server" Text="Enviar"></asp:Button>
</p>
</td>
</tr>
</tbody>
</table>
</form>
<hr />
<h3><asp:Label id="saida" runat="server" forecolor="Red"></asp:Label>
</h3>
</body>
</html>


Neste código a string de conexão é obtida pela seguinte linha de código :


Dim MyConn as New OleDbConnection(ConfigurationSettings.AppSettings("strConn"))


Mas onde esta a string de conexão ? Esta no arquivo Web.config. Usando a tag <appSettings> podemos definir como abaixo a string de conexão:


<appSettings>
<add key="strConn" value= "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=d:\inetpub\wwwroot\dados\Acesso.mdb" />
</appSettings>     


A tag appSettings pode declarar configurações específicas da aplicação.


Podemos também definir um arquivo de mensagem de erros personalizada usando a tag customErrors :


<customErrors defaultRedirect="\login\erro\erro.aspx" mode="On" />




qualquer erro não tratado irá exibir a mensagem do arquivo erro.aspx .


A propriedade Mode pode possuir três diferentes valores :


  • ON - determina que todos os erros serão direcionados para a página definida
  • OFF - desabilita o tratamento personalizado de erros
  • RemoteOnly - define que os erros , com exceção das páginas ASP.NET , são mostrados nos clientes remotos e que os erros das ASP.NET são exibidos no host local.


Agora vamos testar a aplicação:


1- Clique aqui para tentar acessar a página login-protegido.aspx (se você não estiver autenticado irá para a página de login)


2- Estando na página login.aspx você verá a dica para usuário/senha tente informar algo diferente e verá que é exibida uma mensagem de login inválido


3- Existe um link na página login.aspx para você tentar acessar a página login-protegido.aspx se você clicar no link será remetido de volta para página login.aspx


4- Quando você informa o usuário e senha correta irá para a página de login.aspx . Neste momento a autenticação esta feita e será gravada ; a partir deste ponto você poderá acessar a página protegida diretamente.


5- Para anular a autenticação clique em Log Out e atualize a página. Você irá para a página de login pois não estará mais autenticado e pode começar a brincadeira novamente.





Fonte:


Macoratti.net

Nenhum comentário:

Postar um comentário

Obrigado por Participar do programero, fique a vontade para agradecer, retificar, perguntar ou sugerir.