Para poder activar la seguridad basada en formularios hemos
de seguir los siguientes pasos:
· Configurar el modo de autenticación modificando
la sección en web.config.
· Denegar a los usuarios anónimos en la sección
· Crear una página de registro.
Se utilizara la siguiente tabla para validar las credenciales
de un usuario, esta tabla además de guardar el username y el password tiene un
campo donde se definen los roles del usuario, tener en cuenta que en caso del
usuario que tenga mas de un rol, estos roles deben estar unidos y solamente
separados por una coma sin espacio
Ahora toca crear un nuevo proyecto, para este ejemplo se
utilizara una aplicación ASP.Net de Web Forms
Se agregara un nuevo ítem de tipo Web Form
Ahora se debe dar click derecho en el proyecto, seleccionar propiedades del proyecto y en el panel que se abre seleccionar la opcion Web que se encuentra en la izquierda de la pantalla para luego modificar
como se muestra(cambiar el IIS Express por Local IIS) a fin de hospedar el proyecto web en el servidor local, luego recordar presionar el botón Create Virtual Directory
Abrir el Inetmgr y buscar en el panel central el icono
Authentication y modificar tal como se muestra a fin de habilitar el modo de autenticacion de formularios en el servidor local de IIS
Ahora toca modificar el web.Config
·
Locations
Por defecto, todos los directorios y subdirectorios, incluyendo archivos, donde se encuentre el web.config estarán protegidos al activar el mecanismo de autenticación. Si necesitamos que alguna ubicación específica tenga permisos diferentes, podemos (1) recurrir a un web.config por cada directorio o (2), mucho mejor, definir elementos en el web.config principal.
Además, en algunos sitios web de negocios, varios empleados
tendrían acceso a un sistema con el fin de realizar tareas específicas. Sin
embargo, cada empleado tendría un papel específico, y las operaciones
específicas que hacer, de acuerdo con la naturaleza de su trabajo o nivel de
seguridad.
ASP.NET proporciona el concepto de los roles que le da a
cada rol una visión diferente en páginas específicas.
<location path="adminRol">
<system.web>
<authorization>
<allow roles="admon" />
<deny users="*" />
</authorization>
</system.web>
</location>
<location path="Usuario">
<system.web>
<authorization>
<allow roles="user" />
<deny users="*" />
</authorization>
</system.web>
</location>
<location path="managerRol">
<system.web>
<authorization>
<allow users="lebb"/>
<deny users="*" />
</authorization>
</system.web>
</location>
·
Validar Credenciales
contra la BD
Para realizar la conexión a la base de datos, se utilizara
el siguiente código que verifica si un usuario está debidamente registrado,
importar estos espacios de nombre
using System.Data.SqlClient;
using
System.Web.Security;
private bool ValidateUser( string userName, string passWord ){
SqlConnection conn;
SqlCommand cmd;
string
lookupPassword = null;
// Buscar nombre de usuario
no válido.
// el nombre de usuario no debe ser un valor nulo y debe
tener entre 1 y 15 caracteres.
if ((null == userName) || (0 ==
userName.Length) || (userName.Length > 15)){
System.Diagnostics.Trace.WriteLine( "[ValidateUser] userName failed." );
return false;
}
// Buscar contraseña no válida.
// La contraseña no debe ser un valor nulo y debe tener
entre 1 y 25 caracteres.
if ((null == passWord)||( 0 ==
passWord.Length )||(passWord.Length > 25)){
System.Diagnostics.Trace.WriteLine( "[ValidateUser] passWord failed." );
return false;
}
try{
conn = new SqlConnection( "server=localhost;Integrated
Security=SSPI;database=pubs" );
conn.Open();
cmd = new SqlCommand( "Select pwd from users where
uname=@userName", conn );
cmd.Parameters.Add( "@userName", SqlDbType.VarChar, 25 );
cmd.Parameters["@userName"].Value = userName;
lookupPassword = (string) cmd.ExecuteScalar();
cmd.Dispose();
conn.Dispose();
}
catch ( Exception ex ){
// Agregar aquí un control de errores para la depuración.
// Este mensaje de error no debería reenviarse al que
realiza la llamada.
System.Diagnostics.Trace.WriteLine( "[ValidateUser]
Exception " + ex.Message );
}
// Si no se encuentra la contraseña, devuelve false.
if ( null == lookupPassword ){
// Para más seguridad, puede escribir aquí los intentos de
inicio de sesión con error para el registro de eventos.
return false;
}
// Comparar lookupPassword e introduzca passWord, usando
una comparación que distinga mayúsculas y minúsculas.
return ( 0 == string.Compare( lookupPassword,
passWord, false ) );
}
·
Cookie de Autenticación
Puede usar dos métodos para generar la cookie de
autenticación de formularios y redirigir al usuario a la página apropiada del
evento cmdLogin_ServerClick. Se proporciona código de ejemplo para ambas
situaciones. Utilice cualquiera de ellos de acuerdo a sus requisitos.
1.
Llame al método RedirectFromLoginPage para
generar automáticamente la cookie de autenticación de formularios y redirigir
al usuario a una página apropiada del evento cmdLogin_ServerClick:
private void cmdLogin_ServerClick(object sender, System.EventArgs e){
if
(ValidateUser(txtUserName.Value,txtUserPass.Value))
FormsAuthentication.RedirectFromLoginPage(txtUserName.Value,
chkPersistCookie.Checked);
else
Response.Redirect("logon.aspx", true);
}
// Cerrar la sesión
FormsAuthentication.SignOut();
También podría ayudar este código
private void cmdLogin_ServerClick(object sender, System.EventArgs
e){
if
(ValidateUser(txtUserName.Value,txtUserPass.Value)){
FormsAuthentication.SetAuthCookie(txtUsuario.Text, false);
Response.Redirect("OtraPagina.aspx");
else
Response.Redirect("logon.aspx", true);
}}
// Cerrar la sesión
FormsAuthentication.SignOut();
2.
Genere el vale de autenticación, cífrelo, cree
una cookie, agréguela a la respuesta y redirija al usuario. Esto le
proporcionará un mayor control sobre cómo ha creado la cookie. También puede
incluir datos personalizados junto con FormsAuthenticationTicket en este caso.
protected void BLogin_Click(object sender, EventArgs e){
FormsAuthentication.Initialize();
string cnx = ConfigurationManager.ConnectionStrings["cnx"].ConnectionString.ToString();
if ((!string.IsNullOrEmpty(txtUsername.Text))
&& (!string.IsNullOrEmpty(txtPassword.Text)))
{
string usuario =
txtUsername.Text.Trim();
string password =
txtPassword.Text.Trim();
using (SqlConnection cnn = new SqlConnection(cnx)){
SqlCommand cmd = cnn.CreateCommand();
cmd.CommandText = "SELECT
Roles FROM Login_ASP WHERE Username=@username " +
"AND Password=@password";
cmd.Parameters.Add("@username", SqlDbType.VarChar, 50).Value = usuario;
cmd.Parameters.Add("@password", SqlDbType.VarChar, 50).Value = password;
cnn.Open();
SqlDataReader reader =
cmd.ExecuteReader();
if (reader.Read()){
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, // Ticket version
usuario, // Username asociado al
ticket
DateTime.Now, // Date/time de creacion
DateTime.Now.AddMinutes(30), // Date/time de expiracion
true, // "true" para persistencia de cookie
reader.GetString(0), // User-data, en
este caso los roles
FormsAuthentication.FormsCookiePath);// Path de la cookie
// Encriptacion de la cookie
string hash = FormsAuthentication.Encrypt(ticket);
// Nombre y valor del Hashed ticket
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
// definir la cookie's expiration
time al tickets expiration time
if (ticket.IsPersistent)
cookie.Expires = ticket.Expiration;
// Agregar la cookie a la lista de outgoing response
Response.Cookies.Add(cookie);
// Redireccionar a la URL solicitada o homepage if no
previous page requested
string returnUrl = Request.QueryString["ReturnUrl"];
if (returnUrl == null) returnUrl = "/";
// Don't call
FormsAuthentication.RedirectFromLoginPage since it
// could replace the
authentication ticket (cookie) we just added
Response.Redirect(returnUrl);
//string rol =
reader.GetString(0).ToString();
//Label1.Text = rol;
reader.Close();
}
else{
// Never tell the user if just the
username is password is incorrect.
// That just gives them a place to
start, once they've found one or
// the other is correct!
Label1.Text = "Username /
password incorrect. Please try again.";
}}}}
Antes de continuar, unos tips básicos al utilizar cookies de
los HttpModules
·
Redireccionamiento Al redireccionar al usuario no usar
el RedirectFromLoginPage para que se puedan usar las Cookies de los HttpModules
Response.Redirect(
FormsAuthentication.GetRedirectUrl(user,false));
·
Verificar usuario autenticado HttpContext .Current.User.Identity.IsAuthenticated
·
Obtener el nombre del usuario HttpContext .Current.User.Identity.Name
·
Comprobar rol del usuario HttpContext .Current.User.IsInRole( "admin" )
Ahora en el archivo Global.asax
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.User != null) //Hay un usuario?
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
//El usuario esta autenticado?
{
if (HttpContext.Current.User.Identity is FormsIdentity) //utilizo Forms?
//if
(HttpContext.Current.User.Identity.AuthenticationType == "Forms")
equivalente al anterior
{
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity; //guardo el actual usuario
en id
FormsAuthenticationTicket ticket = id.Ticket; //tomo toda la informacion
de id en ticket
// Get the stored user-data,
in this case, our roles
string userData = ticket.UserData;
string[] roles = userData.Split(',');
HttpContext.Current.User = new GenericPrincipal(id, roles);
}
}
}
}
Ahora, como pueden ver en la sección Locations, definí tres páginas,
les muestro el código de cada página de acuerdo a las restricciones definidas
anteriormente
managerRols.aspx
public partial class managerRol : System.Web.UI.Page{
protected void Page_Load(object sender, EventArgs e){
string usuario = HttpContext.Current.User.Identity.Name;
Label1.Text = usuario;
}
protected void Button1_Click(object sender, EventArgs e)
{
FormsAuthentication.SignOut();
Response.Redirect("Default.aspx");
}
}
adminRol.aspx
public partial class adminRol : System.Web.UI.Page{
protected void Page_Load(object sender, EventArgs e){
if (HttpContext.Current.User.Identity.IsAuthenticated){
string usuario = HttpContext.Current.User.Identity.Name;
Label1.Text = usuario;
}}
protected void Button1_Click(object sender, EventArgs e){
FormsAuthentication.SignOut();
Response.Redirect("Default.aspx");
}
}
Ususario.aspx
public partial class Usuario : System.Web.UI.Page{
protected void Page_Load(object sender, EventArgs e){
if (User.IsInRole("user")) {
Label1.Text = "Bienvenido
Usuario";
}
}
}