Hay varias formas de hacer la autenticación de usuarios en ASP. Web Forms es la más simple de utilizar, pero es un poco excesivamente básica, y normalmente solo podemos almacenar el nombre de usuario. Como explique en este post para obtener el Id del Usuario podemos obtener dicho dato, o si almacenamos un JSON, u otro formato, podemos almacenar algo más que el nombre de usuario. Pero este método, básico y fácil de implementar, también tiene sus contras, entre ellos, que es muy específico para WebFoms.
Hoy te traigo una solución que he encontrado cuando estaba empezando a migrar uno de mis proyectos a MVC. Este método funciona tanto para ASP.NET MVC como para ASP.NET WerbForms, y es muy simple de implementar. Dándonos muchas más opciones de configuración, control, y sobre todo, velocidad de gestión luego en la página.
Agradecer al autor del post Autenticación Personalizada con ASP.Net y MVC, Julio Cesar Ruperti Ortiz, por ese magífico post. El cual ahora voy a ampliar un poco más, e intentar explicarlo, como siempre hago, un poco más para torpes como yo.
Que necesitamos para empezar.
Vamos a hacer una implementación de autenticación personalizara para WebForms, y para ello vamos a utilizar las clases de interfaces:
- ClaseMembership: Proporciona los servicios de suscripción para la autenticación.
- Clase MembershipUser: Proporciona información sobre un usuario en concreto.
- Clase MembershipProvider: Maneja todas las operaciones que se pueden hacer con los usuarios, como crear, borrar, editar, etc. Es una interfaz entre ASP.NET y la base de datos. En este ejemplo solo vamos a hacer uso de la lectura y la validación del usuario.
- Interfaz Identity: Encapsula toda la información sobre el usuario o entidad que está siendo validado en su nivel más básico.
- Interfaz IPrincipal: Representa el contexto de seguridad del usuario, indica si el usuario está autenticado o no en un rol determinado.
Además debes de tener creado algún sistema de control de usuarios, por ejemplo, una base de datos.
Manos a la obra
En el post original, el cual estoy ampliando y detallando un poco más, tienes un vídeo de todo el proceso, va un poco rápido, y por eso te voy a ir detallando los pasos, además de escribiendo el código, por si prefieres copiar y pegar.
Primero vamos a crear una clase que hereda desde MembershipUser para la definición de los datos de usuario que vamos a necesitar, o que queremos recoger. Yo he lo he hecho todo en un solo archivo, llamado SeguridadWeb.cs, pero puedes, como indica en el vídeo, crear un archivo para cada clase que vamos a crear.
public class Usuario:MembershipUser
{
public int IdCliente { get; set; }
public string Nick { get; set; }
public string Pass { get; set; }
public string Nombre { get; set; }
public int Permiso { get; set; }
public string Img { get; set; }
public Usuario (UserDetail usuario)
{
this.IdCliente = usuario.IdCliente;
this.Nick = usuario.Nick;
this.Pass = drualcman.Encriptacion.SHA1(usuario.Password); //encriptar
this.Nombre = usuario.Nombre;
this.Permiso = usuario.Permiso;
this.Img = usuario.img;
}
}
Como puedes observar, le paso un objeto con los datos del usuario, si estas utilizando EntityFramework, este objeto será la tabla con los datos, en mi caso, mi objeto tiene muchas mas cosas y subclases con otros objetos, por lo que no es directamente una tabla. Pero así puedes ver la flexibilidad del sistema. De este objeto solo recogemos los datos que necesitamos.
Ahora vamos a crear una clase que va a manejar la identificación del usuario.
public class IdentityPersonalizado:IIdentity
{
public string Name { get { return this.Nick; } }
public IIdentity Identity { get; set; }
public bool IsAuthenticated => Identity.IsAuthenticated;
public string AuthenticationType { get { return this.Identity.AuthenticationType; } }
public int IdCliente { get; set; }
public string Nick { get; set; }
public string Pass { get; set; }
public string Nombre { get; set; }
public int Permiso { get; set; }
public string Img { get; set; }
public IdentityPersonalizado(IIdentity identity)
{
this.Identity = identity;
Usuario usuario = Membership.GetUser(identity.Name) as Usuario;
this.IdCliente = usuario.IdCliente;
this.Nick = usuario.Nick;
this.Pass = usuario.Pass;
this.Nombre = usuario.Nombre;
this.Permiso = usuario.Permiso;
this.Img = usuario.Img;
}
}
Esta es la clase que va a hacer de intermediario entre ASP y nuestra clase de Usuario para almacenar los datos. Como veis se repiten los mismos datos que en la clase Usuario. Pero si lo deseas puedes suprimir algunos.
Ahora vamos a crear una clase para el manejo de la información con el interfaz IPrincipal el cual nos comunicará las cases.
public class Principal : IPrincipal
{
public bool IsInRole(string role)
{
throw new NotImplementedException();
}
public IIdentity Identity { get; private set; }
public IdentityPersonalizado MiIdentidad
{
get { return (IdentityPersonalizado)Identity; }
set { Identity = value; }
}
public Principal(IdentityPersonalizado identity)
{
this.Identity = identity;
}
}
Y por creamos una clase para implementar el Proveedor Personalizado a nuestra web. En este aso cuando estás creando la clase y creas la herencia de MembershipProvider el propio Visual Studio te a dar la posibilidad de arreglar la clase y te va a poner todas las propiedades necesarias, sin embargo en este ejemplo sólo vamos a utilizar 2, que son las que te voy a copiar aqui.
public class ProveedorAutenticaicon : MembershipProvider
{
public override MembershipUser GetUser(string username, bool userIsOnline)
{
UserDetail usuario = ManejoDatos.CargarUsuario(username); //esta función me recupera los datos del usuario, dependerá de como tu lo manejes
return usuario == null ? null : new Usuario(usuario);
}
public override bool ValidateUser(string uname, string password)
{
bool bResultado;
string pass = drualcman.Encriptacion.SHA1(password);
pass = password;
// Consulta para la base de datos
string strSQL = "[TU CONSULTA EN LA BASE DE DATOS]";
//yo tengo una clase para encapsular el manejo de la base de datos, pero dependerá de cómo obtengas tu los datos del usuario
DDBB cnn = new DDBB();
System.Data.DataTable dt = cnn.ConsultarConDataTable(strSQL);
cnn.Dispose();
cnn = null;
string error = string.Empty;
if (dt.Rows.Count > 0) bResultado = true;
else bResultado = false;
return bResultado;
}
}
Los cambios necesarios para implementar la autenticación personalizada en la web
Ahora ya solo nos queda implementar dicha solución, evidentemente tienes que tener una página para hacer el login, y una página privada a la que llegar cuando haces el login. Doy por sentado que eso ya lo tienes implementado.
En el web.config debes de realizar estos cambios dentro de la seccion system.web:
< system.web >
< authentication mode="Forms" >
< forms loginUrl="/login.aspx" defaultUrl=”/Home” / >
< /authentication>
< membership defaultProvider="MiProveedor" >
< providers >
< clear/ >
< add name="MiProveedor" type="AutenticacionPersonalizada.Seguridad.ProveedorAutenticacion"/ >
< /providers >
< /membership >
< /system.web >
En el archivo Global.asax.cs debemos de agregar esta función, aunque en un prueba rápida en un proyecto de WebForm me olvidé de incluirlo, y me estaba funcionando correctamente, así que, inicialmente, no es necesaria, pero si muy recomendable.
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
if (Request.IsAuthenticated)
{
IdentityPersonalizado identity = new IdentityPersonalizado(HttpContext.Current.User.Identity);
Principal principal = new Principal(identity);
HttpContext.Current.User = principal;
}
}
Esto es todo amigos
Como veis es muy copo código y se puede personalizar como gustes. Happy coding
#seguridad, #ASP, #web #webforms #MVC #CSHARP