ASP .NET - Autenticação/Autorização via código com FormsAuthenticationTicket - 2


No artigo anterior recordamos os conceitos básicos sobre autenticação/autorização com ASP .NET, definimos o nosso objetivo , criamos o projeto no Visual Web Developer 2010 Express e configuramos o nosso arquivo web.config. Vamos continuar criando as pastas, o código e as páginas para permitir o acesso baseado no perfil do usuário.

Gostaria de dizer que existe mais de uma forma de implementar toda essa funcionalidade e vou mostrar uma deles portanto você pode alcançar o mesmo objetivo com algumas variações.

O arquivo web.config é o coração da nossa aplicação pois é ele que vai decidir quem pode ou não pode acessar determinado recurso, e com ajuda de outros recursos podemos por nosso projeto para funcionar.

Vamos criar duas pastas no nosso projeto, clique com o botão direito sobre o nome do projeto e selecione a opção Add -> New Folder e crie as pastas Admin e Aluno.

Obs: A criação das pastas para os outros perfis (funci e mestre) é feita da mesma forma e possui o mesmo funcionamento aplicados às pasta Admin e Aluno.

Vamos incluir em cada uma destas pastas um formulário Web. Clique com o botão direito sobre a pasta Admin e selecione Add -> New Item e escolha o template Web Form e informe o nome admin.aspx, repita o processo e inclua na pasta Aluno a página aluno.aspx.

Obs: Poderia ter usado uma master page para herdar o cabeçalho, fica a seu critério usar este recurso.

O conteúdo das páginas admin.aspx e aluno.aspx será muito simples, apenas um cabeçalho e uma linha de texto para identificar a página. Veja abaixo como deve ficar o leiaute das páginas alunos.aspx e admin.aspx e a estrutura da solução AutenticacaoWEB exibida na janela Solution Explorer;

Figura 1.0 - Página alunos.aspx da pasta Alunos
Figura 2.0 - Página admin.aspx da pasta Admin

Vamos a seguir criar a página de login da aplicação que será usada para autenticar o usuário solicitando seu login e sua senha. A página será bem simples contendo um cabeçalho , dois controles TextBox (ID=txtUsuario e ID=txtSenha ), um controle Button (ID=btnLogin) e um controle Label (ID=lblError) definidos conforme o leiaute abaixo:

Página login.aspx

Precisamos criar também mais duas páginas uma para realizar o logout e a página padrão para a qual o usuário deverá ser direcionado após fazer o login com sucesso.

Para criar a página logout.aspx clique com o botão direito do mouse sobre o nome do projeto e selecione Add-> New Item, escolha o template Web Form e informe o nome logout.aspx a seguir inclua os controles:

página logout.aspx

A página padrão receberá o nome de default.aspx contendo os seguintes controles:

página default.aspx

O fluxo de acesso envolvendo as 5 páginas criadas deverá ser o seguinte:

Neste momento a estrutura da nossa solução exibida na janela Solution Explorer deverá ser a seguinte:

Vamos agora analisar o arquivo web.config e verificar qual a lógica de acesso e permissão implementadas:

Obs: Como não definimos o atributo defaultUrl a página default.aspx será a página para a qual o usuário será direcionado após efetuar o login com sucesso.

Dessa forma pelo que definimos no arquivo web.config, somente os usuários com os perfis criados terão acesso ao site, e, após efetuarem o login deveremos identificar o perfil do usuário redirecionando-o para o respectivo recurso.

Definindo o código do projeto

Vamos agora definir o código usado em cada página do nosso projeto começando com a página login.aspx.

No evento Click do botão Login vamos colocar o código para validar o usuário e definir o seu perfil. No arquivo login.aspx.vb inclua o seguinte código :

- Declaração do namespace: Imports System.Web.Security

O namespace System.Web.Security contém classes que são usadas para implementar a segurança do ASP.NET em aplicativos web.

- Código do evento Click do botão Login:

 Protected Sub btnLogin_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnLogin.Click
        If ValidaUsuario(txtUsuario.Text, txtSenha.Text) Then
            FormsAuthentication.Initialize()
            Dim strPerfil As String = AtribuiPerfil(txtUsuario.Text)

            'Definimos quanto tempo o usuário irá permanecer logado após deixar o site sem efetuar o logout
            Dim fat As FormsAuthenticationTicket = New FormsAuthenticationTicket(1, _
                                                                             txtUsuario.Text, DateTime.Now, _
                                                                             DateTime.Now.AddMinutes(30), False, strPerfil, _
                                                                             FormsAuthentication.FormsCookiePath)
            Response.Cookies.Add(New HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(fat)))
            Response.Redirect(FormsAuthentication.GetRedirectUrl(txtUsuario.Text, False))
        Else
            'exibe a mensagem de erro
            lblError.Visible = True
        End If
    End Sub

O código acima efetua a validação do usuário verificando o login e a senha;. A validação que usei neste exemplo é bem simples e apenas verifica se o nome do usuário é igual a admin,aluno,funci ou mestre e a senha é 123456.

Obs: Esta rotina pode ser construída usando a verificação das credenciais com os valores armazenados em um banco de dados mas por questão de simplicidade eu vou usar apenas uma definição de valores com strings.

 Private Function ValidaUsuario(ByVal strNomeUsuario As String, ByVal strPassword As String) As Boolean
        'Retorna True se o nome e senha do usuário for válido
        Return CBool(strNomeUsuario = "admin" Or strNomeUsuario = "aluno" Or strNomeUsuario = "funci" Or strNomeUsuario = "mestre" AndAlso strPassword = "123456")
    End Function

Se o usuário for válido primeiro atribuímos o perfil conforme o seu nome (no nosso exemplo o nome é igual ao perfil por pura preguiça...) conforme o código abaixo:

Private Function AtribuiPerfil(ByVal strNomeUsuario As String) As String
        'Retorna uma lista do perfil para o usuário
        If txtUsuario.Text = "admin" Then
            Return strNomeUsuario
        ElseIf txtUsuario.Text = "aluno" Then
            Return strNomeUsuario
        ElseIf txtUsuario.Text = "funci" Then
            Return strNomeUsuario
        ElseIf txtUsuario.Text = "mestre" Then
            Return strNomeUsuario
        Else
            Return String.Empty
        End If
    End Function

Em seguida criamos um ticket chamado fat usando a classe FormsAuthenticationTicket();

Criamos um ticket com os dados do usuário e também os perfis carregados e este ticket será a base da nossa autenticação.

A classe FormsAuthenticationTicket é usada para criar um objeto que representa o tíquete de autenticação que é usado pela autenticação de formulários para identificar um usuário autenticado.As propriedades e valores de um tíquete de autenticação de formulários são convertidos para uma cadeia de caracteres criptografada armazenada em um cookie ou na URL.

Os valores de FormsAuthenticationTicket para o usuário atual autenticado podem ser acessados usando a propriedade Ticket da classe FormsIdentity.Você pode acessar o objeto FormsIdentity atual convertendo a propriedade Identity do usuário atual para o tipo FormsIdentity.

Agora temos que criar um arquivo Global.asax e no evento AuthenticateRequest , que ocorre quando um usuário tenta se autenticar, temos que definir uma rotina para carregar os perfis dos usuários para que o ASP .NET os reconheça;

Inclua um arquivo Global.asax no projeto e no evento AuthenticateRequest defina o seguinte código:

 Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs)
        ''Fires upon attempting to authenticate the use
        If Not (HttpContext.Current.User Is Nothing) Then
            'Usando as classes de identidade vamos obter o perfil e carregar na aplicação   
            If HttpContext.Current.User.Identity.IsAuthenticated Then
                If TypeOf HttpContext.Current.User.Identity Is FormsIdentity Then
                    Dim fi As FormsIdentity = CType(HttpContext.Current.User.Identity, FormsIdentity)
                    'obtém o ticket de autenticação
                    Dim fat As FormsAuthenticationTicket = fi.Ticket
                    Dim astrPerfis As String() = fat.UserData.Split("|"c)
                    HttpContext.Current.User = New GenericPrincipal(fi, astrPerfis)
                End If
            End If
        End If
    End Sub

Se o usuário for válido e for autenticado com sucesso será direcionado para a página default.aspx. Nesta página exibimos o nome do usuário usando o controle LoginName e no controle Hyperlink vamos definir de forma dinâmica as seguintes propriedades do controle:

A seguir temos o código no evento Load que vai tomar essas decisões definindo essas propriedades conforme o perfil carregado do usuário atual;

 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        lblAviso.Text = "Benvindo : "
        If Page.User.IsInRole("admin") Then
            hplPerfil.NavigateUrl = "~/Admin/admin.aspx"
            hplPerfil.Text = "Acesso a página de Administração"
            hplPerfil.Visible = Page.User.IsInRole("admin")
        ElseIf Page.User.IsInRole("aluno") Then
            hplPerfil.NavigateUrl = "~/Aluno/aluno.aspx"
            hplPerfil.Text = "Acesso a página de Notas"
            hplPerfil.Visible = Page.User.IsInRole("aluno")
        ElseIf Page.User.IsInRole("funci") Then
            hplPerfil.NavigateUrl = "funci.aspx"
            hplPerfil.Text = "Acesso a página de Cadastro de Alunos"
            hplPerfil.Visible = Page.User.IsInRole("funci")
        ElseIf Page.User.IsInRole("mestre") Then
            hplPerfil.NavigateUrl = "mestre.aspx"
            hplPerfil.Text = "Acesso a página de Planejamento de Cursos"
            hplPerfil.Visible = Page.User.IsInRole("mestre")
        End If
    End Sub

Agora só falta definir o código da página logout.aspx para que a sessão seja encerrada e o ticket de autenticação de formulários seja removido do navegado;

Fazemos isso incluindo o código abaixo no evento Load da página:

 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Session.Abandon()
        'remove o tickect de autenticação
        FormsAuthentication.SignOut()
    End Sub

Agora só falta testar:

Executando o projeto será apresentada a página login.aspx (pois negamos o acesso a todos os usuários ao raiz do site);

Após efetuar o login com o perfil aluno informando um login e senha válidos será apresentada a página default.aspx exibindo o nome do usuário logado , o texto e link para acesso à página /Aluno/aluno.aspx;

Ao clicar no link o usuário terá acesso a página aluno.aspx conforme figura abaixo:

Como eu já mencionei existem outras maneiras de obter o mesmo resultado e em outro artigo irei mostrar isso usando a linguagem C#.

Pegue o projeto completo aqui: AutenticacaoWEB.zip

Eu sei é apenas ASP .NET, mas eu gosto...

Simples, simples assim...

Referências:

José Carlos Macoratti