Geral

Autenticação ASP.NET Personalizada – Usando Rules

Ola Pessoal

Muita gente pergunta como criarmos um sistema de autenticação eficiente em ASP.NET, sem utilizar Profile e a estrutura de tabelas própria do ASP.NET. Pois bem vou mostrar aqui uma maneira bem simples de criar este sistema de forma personalizada utilizando também regras de acesso.

Bom para efetuar nossa exmplicação vamos partir de um exemplo real. Imaginando que criamos uma estrutura de tabelas em nosso banco capaz de armazenar as informações dos usuários, como dados básicos e perfis de acesso, esta estrutura pode ser modelada da maneira que preferir. Abaixo vou citar um exemplo:

image

Neste exemplo simples criamos uma tabela de usuários, uma tabela de perfil que irá armazenar as regras de acesso, e uma tabela UsuarioxPerfil que vamos relacionar as regras de acesso de cada usuário para o sistema.

Agora precisamos criar nossa código para autenticação. Primeiro criamos algumas procedures de consulta as informações, seguindo nosso exemplo criamos uma procedure exemplo para o retorno des dados do usuário:

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:        Adriano Bertucci
-- Create date: 02 de janeiro de 2009
-- Description:    Busca Informações para login no sistema
-- =============================================
ALTER PROCEDURE [dbo].[CPBB_Logar] 
    @Login as varchar(20),
    @Senha as varchar(50)
AS
BEGIN
    SET NOCOUNT ON;
    
    --Retorna as Regras(Perfil) caso o usuário e senha sejam válidos
    SELECT P.PerfilId,P.Nome FROM Usuario U
    LEFT JOIN UsuarioxPerfil UP
    ON U.UsuarioId = UP.UsuarioId
    LEFT JOIN  Perfil P
    ON UP.PerfilId = P.PerfilId
    WHERE U.Login = @Login and U.Senha = @Senha

END

Acima temos o código de uma simples procedure que ira retornar as regras de acesso do usuário de acordo com a validação de usuário e senha.

Agora vamos ao código .NET, com nosso projeto ASP.NET criado usaremos os métodos de autenticação do próprio ASP.NET. Como primeiro passo criei um componente de login que o qual colocarei o código de autenticação conforme descrito abaixo:

protected void btnLogar_Click(object sender, ImageClickEventArgs e)
{
    //Busca os controles com o usuário e senha digitados pelo usuário
    string Login = ((TextBox)LoginView.FindControl("txtLogin")).Text;
    string Senha = ((TextBox)LoginView.FindControl("txtSenha")).Text;

    //Executa a função logar a qual dispara a procedure e retorna
    //o perfil de acesso
    string Perfil = CPBB.Servico.Usuario.Logar(Login, Senha);

    //Verifica o retorno do login
    if (!String.IsNullOrEmpty(Perfil))
    {
        #region " === Autenticação === "
        //Inicializamos o processo de autenticação
        FormsAuthentication.Initialize();

        //Criamos um ticket com os dados do usuário
        //reparem que passamos inclusive os perfis carregados
        //o ticket será a base da nossa autenticação
        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, Login, DateTime.Now, 
        DateTime.Now.AddMinutes(Convert.ToInt32(ConfigurationManager.AppSettings["CookieTimeOut"])), 
        false, Perfil, FormsAuthentication.FormsCookiePath);

        //Criptografamos o ticket por questão se segurança
        string hash = FormsAuthentication.Encrypt(ticket);
        //Criamos um cookie(será usado para validação do asp.net)
        HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
        //Setamos a persistencia do cookie
        if (ticket.IsPersistent) cookie.Expires = ticket.Expiration;

        //Em fim adicionamos o cookie a nossa aplicação.
        Response.Cookies.Add(cookie);
        //Retornamos para a página que foi solicitada
        string returnUrl = Request.QueryString["ReturnUrl"];
        if (returnUrl == null) returnUrl = "/";
        Response.Redirect(returnUrl);
        #endregion
    }
    else
    {
        ScriptManager.RegisterStartupScript(Page, Page.GetType(), "Login", "alert('" + 
                                         Resources.MensagensAlertas.LoginInvalido + "');", true);
    }
}

Apenas como demonstração segue abaixo a função de login a qual é utilizada para a consulta ao banco de dados em nosso exemplo representada por CPBB.Servico.Usuario.Logar(Login, Senha);

public static string Logar(string Login, string Senha) 
{
    string Perfil = string.Empty;
    //Consultamos o banco de dados para validar o usuário
    SubSonic.StoredProcedure SP = CPBB.DAL.SPs.CpbbLogar(Login, FormsAuthentication.HashPasswordForStoringInConfigFile(Senha,"sha1"));
    
    System.Data.DataSet ds = SP.GetDataSet();

    CPBB.DAL.PerfilCollection cperfil = new CPBB.DAL.PerfilCollection();
    cperfil.Load(ds.Tables[0]);


    //Carregamos o(s) perfil(s)
    foreach (CPBB.DAL.Perfil perfil in cperfil) 
    {
        Perfil += perfil.Nome + ",";
    }

    cperfil = null; 
    SP = null;
    ds.Dispose();
    return Perfil;
}

Bom pessoal, feito isso agora temos que configurar nosso Global.asax, ele será o responsável por carregar os perfis do usuário para que o ASP.NET o reconheça. Vamos ao código:

protected void Application_AuthenticateRequest(Object sender,EventArgs e)
{
    //Verificamos a existencia de um usuário na aplicação
    if (HttpContext.Current.User != null)
    {
        //Se o usuário esta autenticado( passou pelo login inicial )
        if (HttpContext.Current.User.Identity.IsAuthenticated)
        {
            //Usando as classes de Identidade do ASP.NET vamos pegar as regras
            // e carregar para a aplicação
            if (HttpContext.Current.User.Identity is FormsIdentity)
            {
                FormsIdentity id =(FormsIdentity)HttpContext.Current.User.Identity;
                FormsAuthenticationTicket ticket = id.Ticket;

                string userData = ticket.UserData;
                string[] roles = userData.Split(',');
                HttpContext.Current.User = new GenericPrincipal(id, roles);
            }
        }
    }
}

Repare que utilizamos o método Application_AuthenticateRequest do Global.asax, ele é usado sempre que um usuário se autentica na aplicação.

Feito isso agora basta usar as configurações no web.Config para setar o acesso as páginas, como por exemplo:

<location path="admin">
  <system.web>
    <authorization>
      <allow roles="Administrador"/>
      <deny users="*"/>
    </authorization>
  </system.web>
</location>

Bom pessoal tentei demonstrar de maneira rápida de fazer uma autenticação via asp.net usando roles, caso tenha alguma dúvida é só avisar!

Bom divertimento!


Bookmark and Share

3 Comments

  1. Opa… muito bom seu post.
    Sou novato em ASP.NET e gostaria de pedir um help. No meu Global.aspx a linha HttpContext.Current.User = new GenericPrincipal(id, roles);
    da erro:
    Error 1 The type or namespace name ‘GenericPrincipal’ could not be found (are you missing a using directive or an assembly reference?)
    Pode me ajudar?
    Obrigado.

  2. Opa,
    Ótimo post.
    Como associo os grupos criados no Sharepoint com as roles do web.config ? Como associo usuários à role Administrador?

Deixe uma resposta