Introducción
Este artículo intentara plantear la forma en que se puede crear un login que pueda ser usado tanto para un entorno Web, como para uno WinForms.
Se vera como mediante la definición de funcionalidad en una capa de Servicio el código de autenticación puede ser reutilizado, en realidad este nombre que le he dado a la capa podría llevar cualquier otro nombre, podrías ser directo la capa de Datos, o un Repository, la idea es mantener la técnica que permita reutilizar la funcionalidad.
Algo particular que encontraran en el ejemplo esta referido al password no se guarda de forma plana en la db, sino que por motivos de seguridad se aplica una función de hash.
La misma tiene una particularidad interesante, ya que el algoritmo solo se puede aplicar en un solo sentido, siempre obteniendo el hash de un texto o mensaje, pero nunca de un valor hash obtener el mensaje original.
Al aplicar el algoritmo hash a un mensaje, el resultado será siempre el mismo, por lo tanto esta técnica utilizada en el login permite que el password este siempre seguro. En el ejemplo verán como en el momento de login se aplica el algoritmo al la entrada del usuario y este valor se busca como password en la tabla, al asegurarse que un mismo texto produce el mismo resultado de hash, si se ingreso correctamente usuario y password este debe coincidí con el presente en la base de datos.
Definición de la capa de Servicio
El primer paso que explicaremos en el articulo es el código común que será reutilizado tanto por la capa web como winform, se trata de la denominada capa de servicio.
La misma básicamente se compone de una fachada estática, con métodos para autenticar o insertar un usuario, por supuesto la funcionalidad adicional para actualizar no se incluyo en el ejemplo, pero podrías agregarse si fuera necesario.
public static bool Autenticar(string usuario, string password) { string sql = @"SELECT COUNT(*) FROM Usuarios WHERE NombreLogin = @nombre AND Password = @password"; using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString())) { conn.Open(); SqlCommand command = new SqlCommand(sql, conn); command.Parameters.AddWithValue("@nombre", usuario); string hash = Helper.EncodePassword(string.Concat(usuario, password)); command.Parameters.AddWithValue("@password", hash); int count = Convert.ToInt32(command.ExecuteScalar()); if (count == 0) return false; else return true; } }
public static UsuarioEntity Insert(string nombre, string apellido, string nombreLogin, string password) { UsuarioEntity usuario = new UsuarioEntity(); usuario.Nombre = nombre; usuario.Apellido = apellido; usuario.NombreLogin = nombreLogin; usuario.Password = password; return Insert(usuario); } public static UsuarioEntity Insert(UsuarioEntity usuario) { string sql = @"INSERT INTO Usuarios ( Nombre ,Apellido ,NombreLogin ,Password) VALUES ( @Nombre, @Apellido, @NombreLogin, @Password) SELECT SCOPE_IDENTITY()"; using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString())) { SqlCommand command = new SqlCommand(sql, conn); command.Parameters.AddWithValue("Nombre", usuario.Nombre); command.Parameters.AddWithValue("Apellido", usuario.Apellido); command.Parameters.AddWithValue("NombreLogin", usuario.NombreLogin); string password = Helper.EncodePassword(string.Concat(usuario.NombreLogin, usuario.Password)); command.Parameters.AddWithValue("Password", password); conn.Open(); usuario.Id = Convert.ToInt32(command.ExecuteScalar()); return usuario; } }
El método importante en estos dos métodos es el siguiente:
string password = Helper.EncodePassword(string.Concat(usuario.NombreLogin, usuario.Password));
Esta línea es la que arma el password real que se salvara en el campo de la tabla, como se observa para una seguridad aun mayor se une el nombre del usuario y el password, pasándolos luego por la función que aplica el hash.
internal class Helper { public static string EncodePassword(string originalPassword) { SHA1 sha1 = new SHA1CryptoServiceProvider(); byte[] inputBytes = (new UnicodeEncoding()).GetBytes(originalPassword); byte[] hash = sha1.ComputeHash(inputBytes); return Convert.ToBase64String(hash); } }
En el método Autenticar() como se había comentado no se obtiene el password que originalmente el usuario tienen, sino que se aplica el hash sobre los valores ingresados al momento de realizar el login, ejecutando el query con esta información como filtro.
Si el usuario y password ingresados en la autenticación son los correctos al aplicar el hash retornara la misma cadena que se tiene en la tabla, por lo tanto al ejecutar el query debería devolver el registro del usuario.
Autenticación desde una aplicación Winform
En el método Main() del archivo Program.cs se encontrara la llamada a el formulario que será responsable de al autenticación.
static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); frmLogin frm = new frmLogin(); frm.ShowDialog(); if(frm.DialogResult == DialogResult.OK) Application.Run(new frmPrincipal()); } }
El formulario de login (frmLogin.cs), tendrá un código muy simple, solo tomara el usuario y password invocara al servicio y según el resultado retornara la respuesta al método Main() para que se abra o no el formulario principal.
private void btnAceptar_Click(object sender, EventArgs e) { string nombre = txtNombre.Text; string password = txtPassword.Text; if (LoginService.Autenticar(nombre, password)) this.DialogResult = DialogResult.OK; else this.DialogResult = DialogResult.Abort; } private void btnCancelar_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; }
Adicionalmente se agrego un formulario para la creación de nuevos usuarios, si bien en este no se ha programado la edición completa del usuario, o sea toda la funcionalidad de ABM, el Insert permitirá analizar como se registra un nuevo usuario y se guarda su password.
private void btnAceptar_Click(object sender, EventArgs e) { UsuarioEntity usuario = new UsuarioEntity(); usuario.Nombre = txtUsuario.Text; usuario.Apellido = txtApellido.Text; usuario.NombreLogin= txtNombreLogin.Text; usuario.Password = txtPassword.Text; usuario = LoginService.Insert(usuario); MessageBox.Show(string.Format("Se ha creado el usuario, ID: {0}", usuario.Id)); }
Nuevamente gracias a la funcionalidad encapsulada del Servicio, el código del formulario es muy simple.
Autenticación desde una aplicación Web
La autenticación en un entorno web es algo distinta a una aplicación Windows, en este caso se ha configurado en el web.config, las líneas necesarias para que todo el sitio este bajo una autenticación por medio de “Forms”
<authentication mode="Forms"> <forms name="appNameAuth" path="/" loginUrl="frmLogin.aspx" defaultUrl="Default.aspx" protection="All" /> </authentication> <authorization> <deny users="?" /> </authorization>
En el archivo de configuración del sitio se especifica cual será la pagina por defecto y cual la de login, de esta forma si no hay usuario autenticado, solo el sitio redirección a estas url.
El formulario web frmLogin.aspx tiene un código muy simple:
protected void ProcessLogin(object sender, EventArgs e) { if (LoginService.Autenticar(txtUser.Text, txtPassword.Text)) { FormsAuthentication.RedirectFromLoginPage(txtUser.Text, chkPersistLogin.Checked); } else ErrorMessage.InnerHtml = "<b>Usuario o contraseña incorrectos...</b> por favor re-ingrese las credenciales..."; }
Como se observa luego de la autenticación se hace uso de los métodos provistos por .net en el namespace System.Web.Security, para trabajar con al seguridad.
Aquí se esta indicando el nombre del usuario que paso la validación, y esto hace que solo el sitio se redireccione a la pagina marcada por defecto en el web.config.
En la pagina principal del sitio se ha agregado algo de código para mostrar el nombre del usuario autenticado, y dar la posibilidad de un logout.
protected void Page_Load(object sender, EventArgs e) { Label1.Text = string.Format("Bienvenido al Sistema: {0}", Thread.CurrentPrincipal.Identity.Name); } protected void Menu1_MenuItemClick(object sender, MenuEventArgs e) { if (Menu1.SelectedValue == "Salir") { FormsAuthentication.SignOut(); FormsAuthentication.RedirectToLoginPage(); } }
También se ha creado una pagina para crear nuevos usuarios (Usuarios.aspx)
protected void btnAceptar_Click(object sender, EventArgs e) { UsuarioEntity usuario = new UsuarioEntity(); usuario.Nombre = txtNombre.Text; usuario.Apellido = txtApellido.Text; usuario.NombreLogin = txtLogin.Text; usuario.Password = txtPassword.Text; usuario = LoginService.Insert(usuario); ClearControls(); lblMessage.InnerHtml = string.Format("Se ha creado el usuario, ID: {0}", usuario.Id); } protected void btnCancelar_Click(object sender, EventArgs e) { Response.Redirect("~/Default.aspx"); } private void ClearControls() { txtNombre.Text=""; txtApellido.Text=""; txtLogin.Text=""; txtPassword.Text=""; }
Código de ejemplo
Como requerimiento será necesario contar con al menos Sql Server Express 2008, para que pueda ejecutarse la aplicación.
La tabla de usuario ya posee un registro para ingresar la primera vez, la información es la siguiente:
Usuario: admin
Password: pass123
Para no tener dos base de datos iguales, se agrego un Build Event en el proyecto web para que copie la db desde el proyecto de Class Library a la carpeta App_Data del sitio Web.
Puede que a veces si se compila repetida veces la compilación lance un error al intentar copiar la db a la carpeta App_Data, cuya operación no pueda hacerlo porque el servicio de sql server la tenga loqueada, en ese caso simplemente ejecuten a pesar de este mensaje de error, ya que funcionara sin problemas.
[C#] |
[VB.NET] |
muy buen tutorial, intentaré adaptarlo ahora a una base MySQL a ver que pasa. La duda que me queda es si a la tabla de usuarios puedo agregarle más columnas
ResponderEliminarhola
ResponderEliminarque bueno que resulte util
si este diseño no esta cerrado para nada, las tablas como habras visto las cree yo con los campos que vi utiles para el ejemplo, pero si necesitas poner mas campos puedes hacerlo sin problemas.
Ya sea que uses una db Sql Server, Access o MySql, no afecta, solo que no podrias usar el ejemplo de codigo de forma directa, deberas reemplazar el provider de Sql Server de ado.net por su equivamente en MySql, o sea donde dice SqlConnection, seguro usaras MySqlConection y asi con el resto de los objetos, pero la tecnica se mantiene sin cambios
Es mas el tema del hash por ser un simple string tampoco se ve afectado.
saludos
Buenísimo, ahora a ponerme a programar y dps te cuento, muchísimas gracias!
ResponderEliminarHola, muy buen tutorial
ResponderEliminarTengo una duda,para winform
si yo me conecto a oracle en mi cadena de conexion tengo el usuario y la contraseña y la base de datos, pero cada cierto tiempo necesito cambiar esta contraseña, entonces cuando el usuario se logea y verifica que ya caduco debe cambiar la contraseña pero al ser la contraseña de la cadea de conexion me da error, como se podría realizar esto? muchas gracias.
hola asukitta
ResponderEliminarEl tema es que la contraseña de tu connection string no deberia porque cambiar, deberia ser fija.
Lo que expone este articulo es como implementar la autenticacion de un usuario pero del negocio de tu aplicacion, no de la conexion a la base de datos.
Se supone que la info de la cadena de conexion no deberia variar, porque es logico que esta en un string y no es simple modificar.
Apunto a que no solo es dificil de cambiarlo en cada cliente que use la aplicacion, sino que tambien hay que sincronizar el cambio con Oracle.
En sql server para esto casos se usa la seguridad integrada con windows, de esta forma no hace falta especificar un usuario y password en la cadena de conexion, se usa el mismo usuario que se autentico a Windows, cuando realizo el logon.
mira este link:
OracleConnection.ConnectionString (Propiedad)
por ahi en Oracle tambien puedas implementar seguridad integrada.
Connection strings for Oracle
veras que usa:
Data Source=MyOracleDB;Integrated Security=yes;
Por ahi tambien puedas implementarlo si es que Oracle puede usuar a los usuario de un Dominio de Windows.
saludos
Leandro muy buen post, solo queria hacerte una consulta, en el caso de que quisiera hacer que en el form de login se tengan 3 intentos para ingresar la contraseña, como deberia quedar el codigo en el frmlogin, ya que por mas que intente luego de que se pulsa el botno aceptar se cierra este form. Saludos
ResponderEliminarhola Fernando
ResponderEliminardisculpa la tardanza en la respuesta
se me ocurre que podria ser algo como esto:
private int intentos = 0;
private void btnAceptar_Click(object sender, EventArgs e)
{
string nombre = txtNombre.Text;
string password = txtPassword.Text;
if (LoginService.Autenticar(nombre, password))
this.DialogResult = DialogResult.OK;
else
{
if(intentos == 3)
this.DialogResult = DialogResult.Abort;
else
{
txtNombre.Text = "";
txtPassword.Text = "";
intentos++;
}
}
}
Como veras la variable intentos estara definida a nivel del la clase del formulario
saludos
Hola, Leandro.
ResponderEliminarMuy útil tu post. Pero lo he visto un poquito tarde pues ya diseñé la parte del Login, pero lo hice también con HashCode, sólo que no usé MD5, sino que empleé la función GetHashCode de las cadenas. Algo así como:
int nHash = this.txtPwd.Text.GetHashCode();
Pero me queda preguntar si hay algún inconveniente en ello. Es decir, ¿debería cambiarlo?
Muchas gracias!
hola AlexLander
ResponderEliminarEn principio el resultado deberia ser el mismo.
Solo que como veras en el articulo para otorgar algo mas de seguridad la clave es compuesta, o sea se cifra tanto el password, como el nombre del usuario.
Ademas en el ejemplo no se aplica directo en un control Textbox, sino que se realiza en una clase de mapeo de datos, por lo tanto hay que recurrir a otra funcionalidad.
Pero si en tu caso aplica bien como lo has usado, es valido.
saludos
Gracias Leandro, te lo has currado. Me viene muy bien tu trabajo, 2 libros y en ninguno tan claro como en tu artículo.
ResponderEliminarNuevamente gracias por tu esfuerzo!.
estimado podria subir denuevo el cod de ejemplo... no puedo hacer funcionar...
ResponderEliminarclass LoginService
{
public static bool Autenticar(string usuario, string password)
{
string sql = @"SELECT COUNT(*)
FROM Usuarios
WHERE NombreLogin = @nombre AND Password = @password";
using (SqlConnection conn = new SqlConnection("Data Source=ENZZO-PC\\SQLEXPRESS;Initial Catalog=ISW;Integrated Security=True"))
{
conn.Open();
SqlCommand command = new SqlCommand(sql, conn);
command.Parameters.AddWithValue("@nombre", usuario);
string hash = Helper.EncodePassword(string.Concat(usuario, password));
command.Parameters.AddWithValue("@password", hash);
int count = Convert.ToInt32(command.ExecuteScalar());
if (count == 0)
return false;
else
return true;
}
}
public static UsuarioEntity Insert(string nombre, string apellido, string nombreLogin, string password)
{
UsuarioEntity usuario = new UsuarioEntity();
usuario.Nombre = nombre;
usuario.Apellido = apellido;
usuario.NombreLogin = nombreLogin;
usuario.Password = password;
return Insert(usuario);
}
public static UsuarioEntity Insert(UsuarioEntity usuario)
{
string sql = @"INSERT INTO Usuarios (
Nombre
,Apellido
,NombreLogin
,Password)
VALUES (
@Nombre,
@Apellido,
@NombreLogin,
@Password)
SELECT SCOPE_IDENTITY()";
using (SqlConnection conn = new SqlConnection("Data Source=ENZZO-PC\\SQLEXPRESS;Initial Catalog=ISW;Integrated Security=True"))
{
SqlCommand command = new SqlCommand(sql, conn);
command.Parameters.AddWithValue("Nombre", usuario.Nombre);
command.Parameters.AddWithValue("Apellido", usuario.Apellido);
command.Parameters.AddWithValue("NombreLogin", usuario.NombreLogin);
string password = Helper.EncodePassword(string.Concat(usuario.NombreLogin, usuario.Password));
command.Parameters.AddWithValue("Password", password);
conn.Open();
usuario.Id = Convert.ToInt32(command.ExecuteScalar());
return usuario;
}
}
internal class Helper
{
public static string EncodePassword(string originalPassword)
{
MD5 md5 = MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(originalPassword);
byte[] hash = md5.ComputeHash(inputBytes);
return BitConverter.ToString(hash).Replace("-", "");
}
}
}
me tira error en el UsuarioEntity usuario = new UsuarioEntity();
hola Enzzo
ResponderEliminarpodrias poner cual es el mensaje de error que estas teniendo ?
esto se produce cuando abres el proyecto que descargas de este ejemplo, o cuando estas adaptando el codigo a uno propio ?
saludos
Leandro que se necesitaria para aplicar ASP.NET MVC2 a tu ejemplo???
ResponderEliminarSaludos
ResponderEliminar¿Como se podria recuperar la contraseña real? (sin codificaR)
Gracias
Hola Leandro, hoy me inscribí en MSDN y vi tu post. Mi duda es la siguiente: ¿Es mejor hacerlo de esta forma (encriptando la clave en la capa de Servicio) o conviene encriptarlo en una capa superior de forma que se transmita ya encriptado?
ResponderEliminarDesde ya muchas gracias tanto por tu respuesta como por el tiempo que te tomas para crear ejemplos y responder dudas
Saludos
hola Richof
ResponderEliminarSegun veo no deberia se muy distinto, solo cambiaria el lugar donde realizas la validacion siendo un controlador
ASP.Net MVC Framework - Using Forms Authentication
lo que si veo es que no podras usar es el
FormsAuthentication.RedirectFromLoginPage()
sino que deberas asignar el
FormsAuthentication.SetAuthCookie()
y luego hacer el RedirectToAction() a la apgina principal
saludos
hola Enrique
ResponderEliminarLa idea justamente es no poder recuperar el password ingresado, ya que algoritmo hash solo se aplica en una direccion.
Se aplica la misma tecnica que usarias con Windows, en este cuando pierdes la clave no puede loguearte salvo que un admin la resetee, aqui es identico si el usuario pierde el password la idea es que en alguna pantalla alguien con perfil de admin la reasigne para que el usuario luego la cambie.
Pero no se puede recuperar una vez aplicado el hash.
saludos
hola José
ResponderEliminarLa capa de Servicio seria la fachada al sistema, el punto de entrada a la logica del negocio, creo que es un lugar optimo para aplicar la logica de encriptacion.
Sucede que la presentacion no podrias decidir si encriptar o no porque no es su responsabilidad, ademas en este caso no hay una comuniacion remota entre las capas (recuerda que son dll que estan en el \bin del sitio), estas estan en el servidor, lo que se envia de forma plana es la comunicion del postback, pero para segurizar esto deberias encriptar el canal usando SSL.
saludos
Hola Leandro, excelente post. Descargue el archivo que viene en VB y resulta que tengo Visual Basic 2010 y trabajo con SQL 2005. Ahora al abrir el archivo Login, el programa me dice que si quiero actualizar. Le dije que si y se tomo un tiempo. Ahora el unico detalle que tengo es que la base da datos database.mdf no funciona. No se que hacer. Como lo hago para que funcione esto? y luego para exportarlo a como yo trabajo como seria? muchas gracias por tu tiempo. Saludos
ResponderEliminarHola leandro muy buen post qe has ta el dia de hoy es util, yo utilizare este tipo de apicacion para qe un usuario registrado en la bd pueda acceder al siguiente form, el cual contendra una aplicacion qe guardara datos en la BD de mi servidor, mi pregunta es, qe archivos ASP/ASPX debO subir O me pOdrias recomendar un manual para esto, el servidor esta montado en ubuntu server 10.10, de antemano muchas gracias.
ResponderEliminarhola Luis
ResponderEliminarTe comento la mejor forma para saber que subir a un situio es suando las opcion de Publish que brinda el VS
How to: Publish Web Sites (Visual Studio)
en resumen usa esta opcion
imagen
a la cual le indicas un path fisico de tu disco rigido y alli dejara lo que tienes que publicar
saludos
GRACIIAS :D
ResponderEliminarLeandro una consulta...
ResponderEliminarhecho el ejercicio que planteastes y sale bien...logro registrarme y logearme.. pero cuando quiero acceder de otro proyecto osea logearme no puedo! y eso que aplico el mismo metodo del hash..
xq sera?? o solo me permite usar el hash en ese mismo proyecto
gracias por la respuesta..
hola Leonel
ResponderEliminarCuando te refieres a proyecto, apuntas al proyecto web o a otro del tipo class library, o es otro punto diferente al cual apuntas.
El hash es solo un algoritmo de encritacion, si envias el texto correcto al aplciarlo ya sea desde un proyecto web o clas library este generara la misma salida como resultado, porque la libreria es la misma.
Pero valida que la entrada de informacion es identica, veras alli que en el ejemplo no uso el passwaord solo para aplciar el hash, sino que uno mas de un valor, de esta forma se hace algo mas segura.
Valida que al realziar la autenticacion envias la info correcta, sino no obntendras la misma salida.
saludos
gracias por la respuesta Leandro!
ResponderEliminarbueno si es desktop lo que hecho es hacer yo mismo uno identico al que propones y si me salio, hasta ahi todo bien..pero cuando registro un usuario en tu modelo de ejemplo y luego quiero acceder del mismo que yo hecho,no logro logearme y viceversa, crees que sea por esto:
cmd.Parameters.Add(new SqlParameter("@Nombre", SqlDbType.VarChar,25));
cmd.Parameter["@Nombre"].Value=nom;
yo use "Add" en remplazo de "AddWithValue", lo use al registrar y logear..
gracias
hola leandro tengo una pregunta estoy utilizando tu login pero solo quiero proteger una pagina aspx y no todas como lo puedo hacer... es decir tengo como 5 pestañas y solo quiero proteger la de estadisticas ???
ResponderEliminarhola Leonel
ResponderEliminarEl que no puedas loguarte pueden ser por varios motivos
el incorrecto pasaje de parametros podria ser uno, veo que defines puntualmente un varchar de 25, pero esto podria estar truncando el valor que envias, has probado usando el AddWithValue() con este tampoco funciona ?
Recuerda que la constraseña utiliza una logica especial, o sea se une el nombre al password y se aplica el hash para guardar en la tabla, debes replciar esto mismo cuando quieras validar si es correcto el login ingresado
saludos
hola David
ResponderEliminarPuedes indicar por medio de configuracion que carpetas o archivos estas libres de la seguridad definida
Indicar elementos públicos o privados en un mismo sitio de ASP.NET
Veras que definiendo el tag <location ..> puede indicar como aplicar la seguridad a determiandos sitios de tu aplicacion
saludos
Gracias me ha servido de mucho pero tengo otra pregunta...
ResponderEliminar¿como puede el usuario cambiar el paswoord, si lo perdio o solo por seguridad?
creo que se puede recetear la contraseña para que no se pierda ese usuario... como se podria realizar eso
gracias de antemano y disculpa tantas molestias
hola David
ResponderEliminarEn realidad depende de como quieras aplicar el proceso, en el ejemplo si bien la contraseña aplica hash para aumentar la seguridad y no dejar a la vista el password, podrias en el reset tomar cualquier texto, aplica el hash y guardarlo en la tabla de usuario
y como segundo paso tomas ese string que guardaste y lo envias por mail a la cuenta configurada para ese usuario, por supuesto deberas poner un campo de mail obligatorio para poder recuperar la constraseña que se genera sola
para generar la nueva clave existen algoritmos random que genernal cadenas de string
Generating Random Number and String in C#"
cuando tengas ala cadena random del password que lo resetea, como comente aplica el has y lo guardas en la tabla, y luego el password sin encriptar lo envias por mail
saludos
Hola Leandro, use tu ejemplo y me fue de gran ayuda, pero tengo una duda, con este ejemplo existe forma de aplicar autenticacion de usuarios basada en roles usando HttpModules, lo que tengo desarrollado hasta ahora en cuestion de autenticacion es lo que tu posteaste, no se si deba seguir otro camino o con eso mismo pueda usar HttpModules, si me pudieras orientar te lo agradeceré mucho
ResponderEliminarLeandro excelente Blog gracias por compartir tus conocimientos, tengo una consulta, necesito utilizar el coigo del usuario logeado para poder filtrar informacion que solo este relacionada con este usuario y asi por enede solo mostrarle informacion que este solo relacionada con el...
ResponderEliminarde antemano gracias...
hola YesyM
ResponderEliminarte refieres a algo como esto
Autenticación de Usuarios basada en Roles utilizando HTTPModules en ASP .NET
como veras alli tambien se implememetnas bases propias de autenticacion
en realidad la autenticacion dice si puede acceder al sitio o no, pero no indica a que pagina puedes ingresar
esto podris hacerlo con modulos, o sino por medio de el sitemap
Authenticate User by Roles in ASP.NET
saludos
hola Richard
ResponderEliminarhay varias formas de hacerlo
- una podria ser usando el mismo nombre de login, imagino este debe ser unico por usuario, por lo tanto como lo tienes en el
Thread.CurrentPrincipal.Identity.Name
podrias usarlo directo como filtro en la queries
- la otra es que al momento del login recuperes el id del usaurio que se autentica y dejes esa info en una variable de session
entonces tomarias de esta el id que usarias de filtro
saludos
Hola, me parece muy interesante su blog y este aporte, pero no puedo descargar el ejemplo. Me podría ayudar? Doy clic y me da error.
ResponderEliminarHola, me gusta su post y en especial necesito de esta aplicacion, quisiera descargarla pero me da error, me podria ayudar?
ResponderEliminarhola francisco
ResponderEliminarpor un problema temporal con el hosting, las imagenes y archivos no se pueden descargar reemplaza el dominio ltuttini.com.ar por http://200.58.122.109/ltuttini.com.ar, pero este problema es temporal
accede al blog con el IE para que te muestre los lugares dodne deberian estar las imagenes
saludos
Hola Leandro, me ha servido de maravilla el ejemplo pero al momento de ingresar un usuario nuevo me esta enviando un error, Falta punto y coma (;) al final de la instrucción SQL.
ResponderEliminarHice mi BD en access y se loguea perfectamente el usuario usando la funcion de Hash, pero si deceo agregar un nuevo usuario me lanza ese error.
y uso la funcion siguiente:
Public Shared Function Insert(usuario As UsuarioEntity) As UsuarioEntity
Dim sql As String = "INSERT INTO Usuarios (" & _
"Codigo_Usuario " & _
",Cedula " & _
",Nombre_Apellido " & _
",Email " & _
",Clave_Usuario) " & _
"VALUES (" & _
"@NombreLogin, " & _
"@Cedula, " & _
"@Nombre, " & _
"@Correo, " & _
"@Password) " & _
"SELECT SCOPE_IDENTITY()"
Using conn As New OleDbConnection(ConfigurationManager.ConnectionStrings("default").ToString())
Dim command As New OleDbCommand(sql, conn)
command.Parameters.AddWithValue("Codigo_Usuario", usuario.NombreLogin)
command.Parameters.AddWithValue("Cedula", usuario.Cedula)
command.Parameters.AddWithValue("Nombre_Apellido", usuario.Nombre)
command.Parameters.AddWithValue("Email", usuario.Correo)
Dim password As String = Helper.EncodePassword(String.Concat(usuario.NombreLogin, usuario.Password))
command.Parameters.AddWithValue("Clave_Usuario", password)
conn.Open()
usuario.Id = Convert.ToInt32(command.ExecuteScalar())
Return usuario
End Using
End Function
hola
ResponderEliminarno has probado usando
Dim sql As String = "INSERT INTO Usuarios (" & _
"Codigo_Usuario " & _
",Cedula " & _
",Nombre_Apellido " & _
",Email " & _
",Clave_Usuario) " & _
"VALUES (" & _
"@NombreLogin, " & _
"@Cedula, " & _
"@Nombre, " & _
"@Correo, " & _
"@Password); " & _
"SELECT SCOPE_IDENTITY()"
un punto y coma para separar el insert del scope_identity
saludos
Muy bueno su proyecto, sobre todo por la seguridad.
ResponderEliminarme preguntaba si me puede ayudar con algo parecido. tengo una base de datos en sql server 2000, con la tabla de usuarios, lo que nesecito es ingresar desde la web con una session y una ves ingresado puedan hacer ciertas consultas a la base de datos segun corresponda a cada usuario, mejor si es en VB, por que C# no le entiendo bien. Gracias
hola msn
ResponderEliminarbien en realidad la implementacion web aqui esta planteada
lo de la base de datos no afecta en nada, podrias implementar esto mismo con sql 2000 sin problemas, ya que la estructura de la tabla es bien simple.
con respecto a la consulta por usuario imagino apuntas a implementar filtros en als consultas en conde incluyas al usuario como parte del mismo
habria que analziar como las tablas que quieres consultar se relaciona con al tabla de usuario para poder armar los filtros de las queries
saludos
Hola quisiera que por favor me ayude con este codigo de autenticacion me sale el siguiente error: Es incorrecto utilizar una sección registrada como allowDefinition='MachineToApplication' mas allá del nivel de aplicación. Este error puede tener como origen un directorio virtual que no esté configurado como aplicación en IIS.
ResponderEliminarde antemano Gracias.
Ahh estoy utilizando un directorio dentro de mi proyecto al cual para acceder los usuarios tiene que identificarse este directorio tiene su propio web.config
Hola, alguien me puede ayudar con una duda que tengo.
ResponderEliminarhe logrado configurar el proveedor de ASP.NET para que utilice mi base de datos que esta en sql 2000 en el cual ASP.NET me ha añadido otras tablas entre elllas la de usuario el cual funciona muy bien, el problema es que yo ya tengo una tabla asignada para usuario en mi base de datos el cual quiero que sea el utilizado por los que van a acceder a la web. ¿como puedo hacer que mi tabla sea el que utilice ASP.Net? tengo que modificar el System.config?? Ayudeme por favor de antemano le quedo muy agradecido
hola msn
ResponderEliminarPero justamente en este articulo se hace uso de una base de datos y estructura de tablas propia, como estas describiendo
no se usa la estructura que propone asp.net para la seguridad
mas alla que uses sql 2000, y aqui se usa sql 2008, el resto deberia ser perfectamente compatible con lo que planteas
saludos
hola Leonardo..
ResponderEliminardisculpa que sea tan molestoso pero he utilizado tu codigo cambiandole la conexion a mi base de datos, al parecer funciona a la perfeccion pero no logra ingresarar al default del usuario me sale el mensaje "Usuario ocontraceña incorrecta" podra ser por que el campo usuario es numerico?? mi conexion es la siguiente:
connectionStrings
add name="default"
connectionString="Data Source=MI SERVIDOR;Initial Catalog=MIBASE;Integrated Security=True"
providerName="System.Data.SqlClient"
connectionStrings
Muchas Gracias de antemano
hola msn
ResponderEliminarpero este mensaje es porque no puedes conectarte a la db, o porque no pasa la autenticacion que escribes en los textbox de la pagina de login
por ese mensaje parece ser de la validacion de la pagina, no por un problema de conexion a la db
saludos
Hola nuevamente
ResponderEliminarse conecta a la BD, los textbox toman los datos, lo que no entiendo es por que no me muestra el resultado que espero si lo datos introducidos estan en la BD mensionada
Saludos!!!
hola msn
ResponderEliminarla verdad no sabria decirte sin analizar el codigo
pero podrias poner un breakpoint y ver que datos esta tomando para validar si es correcta la info que envias a la query
saluado
Saludos
ResponderEliminarYa he logrado adaptar tu proyecto a mi base de datos y funciona bien. ahora el problema es cuando lo quiero meter dentro de mi proyecto, no me llega a mostrar el nombre del usuario en la pagina Default.aspx, todo corre bien, ingresa bien pero no me muestra el nombre del usuario en la etiqueta Label1. cual podra ser el problema.
Gracias de antemano
hola msn
ResponderEliminarEstas tomando el usuario de
Thread.CurrentPrincipal.Identity.Name
y cuando te autenticas redireccionas usando
FormsAuthentication.RedirectFromLoginPage()
has validado que el codigo pase por dodne asigna el valor al label ?
saludos
Hola Leonardo:
ResponderEliminarla redireccion funciona bien el codigo del label esta bien pero sigue sin mostrar el usuario, sera que tiene que ver al go con que lo estoy usando dentro de una sub carpeta a la que estoy poniendo como privado pero el web.config de la misma no me funciona la authentication asi que lo tube que sacar al web:config general del proyecto solo deje dentro de la carpeta la opcion de authorization. o como puedo hacer para que los dos funcione en el web.config que esta dentro de la carpeta que pretendo dar seguridad
Gracias por tu tiempo!!!
hola msn
ResponderEliminarhay algo que no entiendo, el problea es que no puedes tomar el usaurio que se autentica o que no puede definir una carpeta para que este dentro o fuera de la seguridad de asp.net aplicada al sitio ?
porque son cosas muy distintas
saludos
Hola Leandro:
ResponderEliminarno me muestra el usuario.
mi pregunta es: ¿sera que es por que tengo 2 wib.config? tengo 1 en el proyecto y otro en la carpeta de seguridad a donde tienen que logearse los usuarios y me muestra el error siguiente: Es incorrecto utilizar una sección registrada como allowDefinition='MachineToApplication' mas allá del nivel de aplicación. pero se soluciona cuando saco la Authentication al web.config general
hola leandro
ResponderEliminarcon este codigo me sube al form1:
SqlConnection conx = new SqlConnection("Data Source=joel;Initial Catalog=contabilidad;Integrated Security=True");
try
{
SqlCommand log = new SqlCommand("select usuario,contrasena from loginadm where usuario='" + usuario.Text + "' and contrasena = '" + contrasena.Text + "'", conx);
conx.Open();
log.ExecuteNonQuery();
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(log);
da.Fill(ds, "loginadm");
DataRow dro;
dro = ds.Tables["loginadm"].Rows[0];
if ((usuario.Text == dro["usuario"].ToString() || (contrasena.Text == dro["contrasena"].ToString())))
{
this.Hide();
Form1 a = new Form1();
a.Show();
}
}
catch
{
MessageBox.Show("Clave o Usuario incorrectos");
contrasena.Clear();
usuario.Clear();
usuario.Focus();
}
finally
{
conx.Close();
}
{
lo que quiero saber es:
como lo puedo hacer para desde ese mismo login me pueda llamar tambien al form2 con su usuario y clave normalmente
saludos
Hola Leandro:
ResponderEliminarYa pude hacer funcionar el login era un problema de herencia, gracias por tu ayuda.
Ahora te pido otro favor, ¿como seria para mostrar otro campo de mi tabla aparte del usuario?, osea mostrar 2 campos.
Saludos!!!
hola msn
ResponderEliminarbien si puedes recuperar el nombre del usuario usando
Thread.CurrentPrincipal.Identity.Name
quiere decir que es enombre es unico, UNIQUE en tu tabla en la base de datos, por lo tento este lo usarias en una query hacia la tabla de tu db para recuperar el resto de la informacion que requieras mostrar el usuario
saludos
Hola Leonardo:
ResponderEliminaryo me referia de que al momento de presionar el boton login me pueda pasar dos campos a la pagina default.aspx, de todas maneras me podrias pasar un ejemplillo sencillo del query si no es molestia?? (msnpostal@gmail.com)
Gracias!!!
hola msn
ResponderEliminarla query seria tan simple como consulta la tabla de usuario
SELECT * FROM Usuarios WHERE nombre = @nombre
a este parametro le pasarias el
Thread.CurrentPrincipal.Identity.Name
solo seria esto lo que comente deberia realizarse para obteenr la info adicional del usuario que se autentica
saludos
hola leandro favor de darmele respuesta
ResponderEliminarcon este codigo me sube al form1:
SqlConnection conx = new SqlConnection("Data Source=joel;Initial Catalog=contabilidad;Integrated Security=True");
try
{
SqlCommand log = new SqlCommand("select usuario,contrasena from loginadm where usuario='" + usuario.Text + "' and contrasena = '" + contrasena.Text + "'", conx);
conx.Open();
log.ExecuteNonQuery();
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(log);
da.Fill(ds, "loginadm");
DataRow dro;
dro = ds.Tables["loginadm"].Rows[0];
if ((usuario.Text == dro["usuario"].ToString() || (contrasena.Text == dro["contrasena"].ToString())))
{
this.Hide();
Form1 a = new Form1();
a.Show();
}
}
catch
{
MessageBox.Show("Clave o Usuario incorrectos");
contrasena.Clear();
usuario.Clear();
usuario.Focus();
}
finally
{
conx.Close();
}
{
lo que quiero saber es:
como lo puedo hacer para desde ese mismo login me pueda llamar tambien al form2 con su usuario y clave normalmente
saludos
hola Joel
ResponderEliminarun primer punto que puedo notar es porque no usas parametros en la query, no concatenes el string
despues lo del form2 no quedo claro, porque alli veo que instancia y abres un form1, porque no podrias hacer lo mismo con el form2
ademas si has analizado este articulo veras que el login se implementa anterior al inicio de la aplciacion por lo que el form del login no deberia invocar a ningun otro form, solo deja continuar y define el Application.Run() o no segun se pase la autenticacion
saludos
Hola Leandro:
ResponderEliminarme podrias dar una idea para hacer un reporte de mi base de datos sql utilizando un DataList o cualquier regilla de datos pero que solo muestre los datos correspondientes al usuario identificado. Disculpa las molestias por estas pequeñeces esque estoy empesando con VisualStudio. Gracias!!!!
hola msn
ResponderEliminarpara mostrar informacion con el usaurio que se autentica imagino estas tablas deberian contar con una columan que referencie a la tabla de usuarios
o sea si tienes una tabla de Compras, esta tabla deberia contar con el campo IdUsuario el cuals e relaciona con la tabla de usuario para emntener la integridad
si haces esto el resto es tan simple como en un query poner el filtro WHERE por este campo IdUsuario
saludos
Hola Leandro:
ResponderEliminarsigo con las molestias, el asusnto es que he pasado de esta forma en parametro de identificacion y en la consulta a la bd no me funciona:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
Label1.Text = String.Format("Bienvenido al Sistema: {0}", Thread.CurrentPrincipal.Identity.Name)
Dim username As String
username = Thread.CurrentPrincipal.Identity.Name
End Sub
de que otra forma puedo utilizar el ID del usuario identificado?
Gracias por tu tiempo!!!
hola msn
ResponderEliminarpero alli no veo que estes realizando ninguna consulta, solo muestras el nombre en un label
la rpegunta seria, en ese label puede visualizar correctamente el nombre del usuario que se autentica?
porque si puedes hacerlo solo es cuestion de usar esa infromacion para filtrar el registro en la query que haces a la tabla y recupera el registros
saludos
Hola Leandro:
ResponderEliminaresta es la consulta que hago a la base de datos mediante un DetailsView.
(/asp:DetailsView)
(asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="(% ConnectionStrings:SAAIINT1ConnectionString %)"
SelectCommand="SELECT [nomprs], [apepat], [apemat], [demail] FROM [Ba02Perso] WHERE ([codreg] = @codreg)")
(SelectParameters)
(asp:QueryStringParameter Name="codreg" QueryStringField="label1{0}"
Type="String" /)
(/SelectParameters)
(/asp:SqlDataSource)
(/td)
(/tr)
(/table)
(/asp:Content)
Que otro codigo tendre que aumentar y en que archivo (El label1 toma perfectamente el campo codreg despues de iniciar sesion)
Gracias por tu cooperación
hola msn
ResponderEliminarla verda no he usado mucho el SqlDataSource, pero me genera desconfianza el usar
QueryStringField="label1{0}"
no has probado aplicar esto mismo pero desde codigo, sin el SqlDataSource
saludos
hola Chechomancr
ResponderEliminarla duda o problema cual seria ?
saludos
hola, resulta que tengo una pagina web en el servidor gratuito "yola" ¿que puedo hacer para crear una pestaña con seguridad, osea que requiera login y password?
ResponderEliminarhola Photography
ResponderEliminarque seria una pestaña de seguridad ?
saludos
Hola Leandro, te comento que esto es justo lo que buscaba.
ResponderEliminarPero le he hecho algunas modificacioncillas, me he creado una nueva solución (.sln) y el click del botón aceptar del crear nuevo usuario me entra dos veces y por tanto me inserta dos veces el insert. Corriendo el proyecto desde tu solución no repite el aceptar dos veces pero corriendo desde el mío que está basado en el tuyo me entra dos veces. No sabes el por qué de esto? Yo no entiendo. Si podrías darme luces por favor. Gracias.
Saludos.
hola «Pr!nc3s!ta»
ResponderEliminarno ahs comentado que ti de proyecto estyas desarollando si es web o winforms, ni en que lenguaje programas
pero bueno mas alla de eso valdiad como asignas el evento al boton, porque puede que tenga dos handler identicos repetidos lo que causaria que se lance dos veces aunque presionas solo una
sino prueba de eliminar ese boton y crear uno nuevo, a ver si se elimina el efecto
saludos
Saludos,
ResponderEliminarMe gustaría saber como es el código o la función para decodificar, es decir, sacar el código encriptado y volverlo normal, una cadena string.
Gracias.
hola Steven Gomez
ResponderEliminarno se puede decodificar, el algoritmo hash es en un solo sentido
y eso es lo bueno justamente de este algoritmo el no poder descifrarlo, sino que se trabaja por comparacion, solo un mismo texto identico genera la misma salida
si el password del usuario no lo conoces deberas geenrar uno nuevo
saludos
Buenos dias Leandro un saludo cordial.
ResponderEliminarQuiero hacerte una consulta . excelnete tutorial.
Cómo puedo redireccionar a distintas páginas con perfil, usando este ejempo sin necesidad de ASPmembership.
Se me ocurre usar dropdownlist para el perfil admin, user, otro, pero como lo implementaria ? muchas gracias
hola Orlando Alarcón
ResponderEliminarel tema es que no deberias teenr diferentes paginas por perfil, deberia ser una sola y segun que rol accesa cambiarle o limitarle la funcionalidad a una unica pagina
sino el tema es que despues de autenticas vas a tener que hacer uso del Response.Redirect() para redireccionar donde necesites, no podras usar la info por defecto
es mas la pagina principal luego del login a los sumo tendria que tener un menu y nada de funcionalidad, lo basico como para brindar el acceso a las acciones basicas
saludos
hola leandro quisiera saber que debes cambiar para adaptar el ejemplo a una base de datos 2008 pero que no sea la version express, ya lo intente pero al momento de grabar usuarios me aparece un error con el id cuando toma el valor entero, me dice que no puede ser null
ResponderEliminarhola william
ResponderEliminaren principio si la idea es usar una version full del sql server solo cambiarias el connection string
o sea tomarias el .mdf y lo adjuntas al servicio de sql server y luego cambias en el .config el connection string para que no use el AttachDbFilename
sino que debes poner el
Initial Catalog=database name
o sea
Data Source=yourserver;Initial Catalog=DataBaseName;
saludos
lo que pasa esque la estoy haciendo con una base de datos que yo cree, en sql server 2008 r2 y copie el usuario de tu base de datos a la mia admin pass123 y si me puedo loguear pero al momento de crear un usuario me dice que Object cannot be cast from DBNull to other types. no es express la base de datos que estoy utilizando
ResponderEliminarok ya quedo solucionado, era un problema con el IdUsuario no lo tenia para que se incrementara automaticamente y obviamente marcaba error gracias por ayudar Leandro y Felicidades por tu blog esta muy interesante espero que sigas publicando temas porque son de gran ayuda e interes en hora buena
ResponderEliminarhola leandro tengo una duda, si quisieramos agregar un metodo mas al service web, que es lo que tendriamos que hacer? ya vez que esta el autenticar, insert y agrege uno mas pero cuando intento hacer referencia con LoginService. no me sale el metodo que agrege
ResponderEliminarhola william
ResponderEliminarrecuerda que si agregas un nuevo webmethod al web service debes luego en el cliente una actualizacion del proxy
si haces click derecho en el web reference veras en el menu la opcion para actualizar la referencia al servicio ,de esta forma reconozca el nuevo webmethod agregado
saludos
ok ya quedo, ya me reconoce el nuevo webmethod la verdad esque nunca he utilizado servicios web, pero me estoy dando cuenta de la seguridad que proporcionan al manejar informacion,gracias por el dato
ResponderEliminarHola Leandro, muy bueno tu bloq. Una consulta, tengo una aplicacion en punto net y cuando verifico la contraseña en SQL 2008 no diferencia mayúsculas y minúsculas, tu crees que me puedas ayudar. Te adjunto el código que tengo hecho:
ResponderEliminarFunction Busca_Usuario()
DTAREADER = OBJAUX.BUSCAR("SELECT * FROM USUARIO WHERE Id_Usuario = '" & TxtUsuario.Text & "' and Clave = '" & TxtClave.Text & "'")
If DTAREADER.HasRows Then
While DTAREADER.Read
GIDUSUAR = DTAREADER.Item("Id_Usuario")
GPERFIL = DTAREADER.Item("Id_Perfil")
ENTRA = "SI"
Me.DialogResult = Windows.Forms.DialogResult.OK
Me.Close()
End While
Else
MsgBox("Usuario o Contraseña Inválidos, Verifique", MsgBoxStyle.Exclamation)
End If
DTAREADER.Close()
End Function
hola Gaby
ResponderEliminarestas planteando de forma incorrecta el codigo, deberias usar parametros y no concatenar los valors en un string
revisa el articulo y veras que en ningun momento concateno para armar la query
creo que el problema esta en OBJAUX.BUSCAR() ese metodo en lugar de ayudar termina empeorando el codigo
saludos
Hola leandro he mirado tus tutos y son geniales me gustaria una ayudita en cuanto al login yo quiero tener un boton en la aplicacion que me permita cambiar de user ocea que cuando el de click en ese boton le aparesca el login otra vez y que si el cambie de user no aya problemas
ResponderEliminarhola mykolweb
ResponderEliminarporque simplemente no realizas un
Application.Restart()
con ese seria como cerrar y volver a iniciar la aplicaicon mostrando el login nuevamente
saludos
Hola leandro gracias por la explicación.
ResponderEliminarSolo una consulta no me quedo claro para que concatenas el usuario el password, dices que para mayor seguridad pero me podrías explicar porque mayor seguridad.
hola Cristian Torres
ResponderEliminarrecueerda que el algoritmo del hash puede generar el mismo resultado ante ciertas cadenas de entrada, o sea dos password podrian generar el mismo hash, no es que se de normalmente esta situacion pero puede llegar a darse el caso
es por eso que para reducir este inconveniente se agrega un dato adicional como es el nombre del usuario
saludos
ante todo te felicito por tu trabajo, pero tengo una consulta yo acabo de descargarlo y funciona bien, pero tu pryecto no crea nuevos usuarios Login con su contrseña o si porque en mi pc no crea la contraseña encriptada
ResponderEliminarhola
ResponderEliminarla contraseña no se encripta, se aplica un hash
la verdad es raro que no cree usuario, estas seguro que validas la db correcta?
que tipo de aplciacion desarrollas web, o winforms?
saludos
Hola Leandro una pregunta como puedo indicarle al webform que tengo un usuario "Admin" y solo el pueda crear nuevos usuarios... y ocultar el tap de usuarios en el form. Default y que solo sea visible para el usuario Admin(Admin seria el nombre del login) muchas gracias.
ResponderEliminarhola Norimaki88
ResponderEliminaren ese caso lo idea seria implementar una version custom del RolProvider
Implementing a Role Provider
analiza el ejemplo de implementacion, seguro debas adaptarlo pero es ae sla idea, para que luego puedas usar algun sitemap o sino desde codigo consultar si se esta en el rol y ocukltar o no determinada opcion
saludos
Ok muchas gracias Leandro por contestarme, voy a revisar lo que me comentas y te platico. Y otra cosa se me presento un detalle a la hora de pasar el formLogin a un formulario de la Master en la linea *ErrorMessage.InnerHtml* me marca el siguiente error...(error message.innerhtml is not declared. it may be inaccessible)como puedo solucionar esto. de ante mano gracias.
ResponderEliminarhola Norimaki88
ResponderEliminarpero ErrorMessage que seria ? es un control de validacion de asp.net o es un tag html con el runat=server
ademas si usas el intellisense del VS te arroja como opcion esa propiedad
saludos
es un es un control de validacion de asp.net va dentro del metodo "Protected Sub ProcessLogin" tal ves tenga que ver que meti el codigo del siseño que antes iva en el body ahora va en un content2.. Porque cree un formulario usando la masterPage. Esto para darle el formato a todos mis forms por igual. :S
ResponderEliminarAqui una imagen del error del que te hablo.
ResponderEliminarhttp://sidecia.com/images/banners/error.jpg
hola Norimaki88
ResponderEliminarbien la imagen aclra un poco mas pero igual no veo de dodne sale ErrorMesasage
si es un Label por lo que veo lo has elimiando, si es un <span> osimilar te falta el runat="server"
o sea si buscas ese ErrorMesasage en el proyecto que es ErrorMesasage ? que control se trata
que pasa si solo lo quitas o reemplazas por algun otro control donde mostrar el mensaje
saludos
Gracias estimado Leandro.. ya lo solucione. Lo que pasa es que en un principio probe cambiando el message por un label y no funciono... crei que era por otra cosa pero después de un rato cuando cerré VS y lo intente de nuevo si se pudo. NO se a que se deba tal ves anda fallando mi programa de VS. pero ya quedo con la etiqueta muchas gracias. ahora estoy revisando lo de los roles. para que no cualquier usuario tenga acceso al FrmUsuario y cree cuentas nuevas. voy a revisar lo que me propusiste con anterioridad.
ResponderEliminarHola Leandro.
ResponderEliminarPara poder modificar toda la BD con los datos encriptados como comentas. La manera de realizarlo ¿sería realizando un UPDATE desde c# aplicando el nuevo password? o ¿habría alguna manera de realizarlo desde SQLServer?
Otra pequeña duda.
Estoy trabajando con ASP.NET C#.
Para añadir la función a mi proyecto sería meter un fichero .cs en la carpeta por ejemplo /lib/Encripta.cs y eliminar el namespace projecto
using System;
using System.Security.Cryptography;
using System.Text;
namespace projecto
{
internal class Encriptar
{
public static string EncodePassword(string originalPassword)
{
SHA1 sha1 = new SHA1CryptoServiceProvider();
byte[] inputBytes = (new UnicodeEncoding()).GetBytes(originalPassword);
byte[] hash = sha1.ComputeHash(inputBytes);
return Convert.ToBase64String(hash);
}
}
}
Para poder usarlo desde cualquier parte..
Muchas gracias por tus aportaciones.
hola misretoques
ResponderEliminardisculpa la demora en la respuesta
- la idea es que la aplicacion sea quien realice los cambios de password, como es logica de negocio no creo que sea bueno que se pueda realizar desde la db, de ultima podrias hacer una pequeña aplicacion winform que tenga esta funcionalidad si es que quieres darle esto a algun admin de red
- si estas con c# el namespace es obligatorio, quizas deberias poner el mismo que usa la aplicacion web si es que has creado un web application, lo cual recomiendo
saludos
Gracias por la contestación Leandro.
ResponderEliminaral final lo he puesto dentro del namespace de mi proyecto.
¿El tema de internal o public, es mejor ponerlo en internal?
Lo he dejado en internal. Ya lo tengo funcionando muchas gracias! ;)
Un saludo y Gracias!
Leandro Tuttini
ResponderEliminarGracias por los aportes, la verdad esta muy interesante
Lo he implementado con los cambios necesarios y corre de maravilla, me ha dado nuevas ideas
Nuevamente Gracias
Hola!
ResponderEliminarMe parece muy buena tu explicacion.
Tengo una duda como le puedo hacer para autentificar varios tipos de usuario como son el administrador, empledos y etc.y que este los mande a diferentes paginas. Actualmente estoy programando visual Basic C# WPF.
ojala pudieras ayudarme!
Gracias, Saludos!!
hola
ResponderEliminarquizas podrias usar el
Application.Startup Event
y alli creas el new de la window de login para luego cuando termine de autenticar abrir la que corresponde al rol
para esto codificarias en el App.xaml, analiza este link
Application Management Overview
te va a venir bien conocer lo que puedes hacer antes de iniciar la aplicacion
saludos
Hola Leandro una consulta par que funciona la clase UsuarioEntity
ResponderEliminarhola ksoto
ResponderEliminaresa clase se usa para definir la entidad del usuario que define el modelo del dominio
se usa para recuperar los datos de la db y poder mapear eso a una clase de .net, si modelas en capas se defineen entidades de negocio
saludos
AYUDA!!
ResponderEliminarperdón por las mayusculas pero ando algo desesperada...
No puedo adaptarlo a MySQL, no se como =(
Alguien me puede ayudar?
Gracias y muy bueno el programita.
Gracias!!!
hola Monzy
ResponderEliminarpero en mysql tienes uan tabla de usuario con al menso el nombre y el password ?
porque si es asi solo es cuestion de uar el proveedor de ado.net para mysql
http://social.msdn.microsoft.com/Forums/es/netfxwebes/thread/48867ed7-bad2-4c14-835f-3366d0ac2395
asi podrias usar el MySqlConnection. MySqlCommand, etc
la estructura del codigo es practicamente igual, solo que los parametros en lugar de usar @ usarias ?
saludos
Hola Leandro:
ResponderEliminarYo utilizo los login de 2010 y me funciona todo correctamente, pero tanto si utilizo tú código o el de 2010. ¿hay alguna forma da activar un usuario por código, conociendo el nombre de usuario y su contraseña? en el caso de tú ejemplo -admin- pass123.
esto me solucionaría un problema de autenticación por certificado dígital, porque en el caso que la autenticación sea correcta entraría con un usuario generico. La verdad me estoy volviendo loco para encontrar una solución.
Un saludo y gracias.
hola Gerardo
ResponderEliminarla verdad no entendi, que tiene que ver la definicion de un usuario en tu db con un certificado digital
se supone que los certificado en un entorno wweb son para segurizar el transporte, o sea los usarias para implementar SSL y acceder por medio de https
pero eso no tendria nada que ver con un usuario y password
saludos
Como estas Leandro, he utilizado este código hash gracias a ti y me funciona de maravilla, voy a colocarlo en el nuevo visual studio 2012 y te comento como me va.
ResponderEliminarHola Leandro:
ResponderEliminarMuy bueno tu blog:
Una pregunta, como puedo adaptar tu ejemplo de vb, para que funcione desde una aplicación en silverlight para que autentique contra MSSQL. Muchas gracias de antemano.
Hola Leandro:
ResponderEliminarMuy Bueno tu Blog:
Por favor dime si se puede utilizar este mismo esquema para autenticar y autorizar desde una aplicación de silverlight...?
Gracias de antemano.
hola Carlos
ResponderEliminarla verdad no he aplicado esta tecnica con silverlight seguramente lo que es el modelo de seguridad se pueda usar, pero la forma de autenticar seguramente requiera implementar servicio web para que silverlight se comunique
Authentication in Silverlight using WCF and ASP.NET Membership Provider
por supuesto en el link es un ejemplo que se debe adaptar, pero los servicios wcf podrian usar los metodo de membership para devolver la info
saludos
Hola Leandro, guen tutorial muy interesante
ResponderEliminarHola Leandro
ResponderEliminarSi quisiera actualizar la contraseña del usuario admin, ¿Como la realizaría? ya que es una contraseña con Hash.
hola radx
ResponderEliminarsimplemente la pisas con un UPDATE
podrias ser:
UPDATE tabla SET contraseña = @pass WHERE id = @id
saludos
hola Leandro
ResponderEliminarLo adapte para una base de datos Access e intente hacerlo de esta forma;
Public Sub modificarclave()
Using con As New OleDbConnection(ConfigurationManager.ConnectionStrings("default").ToString())
Dim cmdmodificar As OleDbCommand
Dim password As String = Helper.EncodePassword(String.Concat(txtmensaje.Text, txtmensaje.Text))
Dim sql As String = "update usuarios set [password] ='" + txtmensaje.Text + "' where (Usuarios.usuario = '" + TextBox1.Text + "')"
Try
con.Open()
cmdmodificar = New OleDbCommand(sql, con)
cmdmodificar.ExecuteNonQuery()
cmdmodificar.Dispose()
con.Close()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Error")
End Try
End Using
El detalle es cuando despues de haber actualizdo el password e intento accesar a la aplicación, no ingresa, ademas cuando reviso en la base de datos el campo "password" la contraseña no esta cifrado como cuando estaba antes de actualizar ¿Por que pasa esto?
hola radx
ResponderEliminarme pregunto porque no usas parametros? eso de concatenar en un string no es correcto
ademas si el password lo pones en la variable "password" porque usas txtmensaje.Text ?
saludos
Hola
ResponderEliminarLo que pasa es que realizo una aplicación que te permite recuperar tu contraseña si la olvidas por medio de tu correo electronico, entonces el contenido del txtmensaje.text es el texto que va a mostrar en correo electronico, el txtmensaje contiene la nueva contraseña por eso es que para la consulta en el campo password pongo como valor a este cuadro de texto txtmensaje.text
En cuanto a los parámetros esto seria asi;
ResponderEliminarPublic Sub modificarclave1()
Using con As New OleDbConnection(ConfigurationManager.ConnectionStrings("default").ToString())
'Dim password As String = Helper.EncodePassword(String.Concat(txtmensaje.Text, txtmensaje.Text))
Dim sql As String = "update usuarios set [password] = @password where (Usuarios.usuario = @usuario)"
Try
Dim cmdmodificar As New OleDbCommand(sql, con)
cmdmodificar.CommandType = CommandType.Text
cmdmodificar.Parameters.AddWithValue("@usuario", TextBox1.Text)
Dim password As String = Helper.EncodePassword(String.Concat(TextBox1.Text, txtmensaje.Text))
cmdmodificar.Parameters.AddWithValue("@password", txtmensaje.Text)
con.Open()
cmdmodificar.ExecuteNonQuery()
cmdmodificar.Dispose()
con.Close()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Error")
End Try
End Using
End Sub
Pero no se por que ahora no hace la actualización de la contraseña en la base de datos, tampoco me marca error
yo actualizo los datos de esta manera:
ResponderEliminarPrivate Shared Function UpdateTecnico(CTecnico As TecnicoEntity) As TecnicoEntity
'* Función Para Actualizar Datos del Técnico *
Dim sql As String = "UPDATE Usuarios SET " & _
"[IdUsuario] = @IdUsuario " & _
",[Titulo] = @Titulo " & _
",[Telefono] = @Telefono " & _
",[Extension] = @Extension " & _
",[IdDepartamento] = @IdDepartamento " & _
",[Nombre] = @Nombre " & _
",[NombreLogin] = @NombreLogin " & _
",[Password] = @Password " & _
",[Email] = @Email " & _
",[TipoUsuario] = @TipoUsuario " & _
"WHERE [IdUsuario] = @IdUsuario"
Using conn As New SqlConnection(ConfigurationManager.ConnectionStrings("default").ToString())
Dim command As New SqlCommand(sql, conn)
command.Parameters.AddWithValue("IdUsuario", CTecnico.IdUsuario)
command.Parameters.AddWithValue("Nombre", CTecnico.Nombre)
command.Parameters.AddWithValue("Titulo", CTecnico.Titulo)
command.Parameters.AddWithValue("Telefono", CTecnico.Telefono)
command.Parameters.AddWithValue("Extension", CTecnico.Extension)
command.Parameters.AddWithValue("IdDepartamento", CTecnico.IdDepartamento)
command.Parameters.AddWithValue("NombreLogin", CTecnico.NombreLogin)
command.Parameters.AddWithValue("Password", CTecnico.Password)
command.Parameters.AddWithValue("Email", CTecnico.Email)
command.Parameters.AddWithValue("TipoUsuario", CTecnico.TipoUsuario)
conn.Open()
command.ExecuteNonQuery()
Return CTecnico
End Using
End Function
Claro esta lo que deseas hacer si el usuario olvida la clave se la quieres enviar por mail, no se si se puede hacer usando el metodo Hash. ya que hash lo que hace es encriptar una cadena y compararla con la que esta en la BD que esta encriptada tambien. no se si es posible hacerlo.
hola radx
ResponderEliminarpuede ser que no actualice porque el parametro del usuario no encuantre ningun registro, porque no usas
where usuario = @usuario
en la query
pero valida
int rowafectadas = cmdmodificar.ExecuteNonQuery()
si es que devuelve row afectadas si devuelve cero es que no encontro ningun registro con ese usuario que proporcionas
saludos
hola Enyelber
ResponderEliminaruna vez que aplcias el hash ya no se puede obtener la contraseña original, lo que ahces en ese caso es generar una random y asignas esa para informarla al usuario
este ingresa pero depsues deria cambiarla por una correcta
o sea tu eres quien le genera una nueva password temporal si es que este olvido la que tenia, las contrseñas siemrpe se regeneran, no se pueden recuperar
saludos
muy buen tutorial Leandro, lo estoy adecuando al un proyecto de Windows Mobile, y la BD no entiendo muy bien la estructura de la tabla, haber si por fa me ayudas con eso.
ResponderEliminarhola Felipe
ResponderEliminarestructura de la tabla ? pero si solo define al usuario con su info basica, se podria decir que casi ni tiene estructura
no se que es lo que no se puede entender
saludos
gracias, es la estructura de la tabla. y quisiera saber si usted sabe sobre variables de sesion en C# pero para windows forms. Gracias
ResponderEliminarhola Felipe
ResponderEliminarlo de estructura de tablas sigo si comprenderlo
ademas en windoform no existe el concepto de sesion, este objeto si existe en un desarrollo web
alli la Session tiene un timeout en el que expira, pero en winforms no esta este concepto
saludos
Lo que pasa es que es un login con BD, y pues como se necesita hacer un select, pues se necesita saber como formada la tabla de los usuarios por decirlo asi. Para poder hacer la comparacion. Gracias
ResponderEliminarhola Felipe
ResponderEliminarPero podrias usar la estructura que aplico en este articulo, algo simple un id de usuario, un nombre y password, con eso basico ya puedes autenticar a un usuario
me pregunto este articulo lo leiste y entendiste ? porque lo que planteas esta alli, es mas uso un select como mencionas
saludos
Hola Leandro, me ha interesado mucho el post dado que he estado trabajando con variables de sesion y claramente no es buena idea, solo tengo una duda; en el caso de que quiera substituir el form por default al que redirige la aplicación es decir en FormsAuthentication.RedirectFromLoginPage(txtUsuario.Text, false). Me di cuenta que hay un tercer parametro en el cual le puedo indicar el path pero no me funciona o talvez no lo estoy haciendo bien.
ResponderEliminarLo hice asi:
FormsAuthentication.RedirectFromLoginPage(txtUsuario.Text, false, "~/Management/menu.aspx");
pero me sale el error que no se encuentra el la pagina "default.aspx". Me ayudas pls? :)
hola EddieF
ResponderEliminarlo que veo en la doc del msdn es que ese path corresponde a las cookies
FormsAuthentication.RedirectFromLoginPage (Método) (String, Boolean, String)
para redireccionar de forma concreta deberias dejar de eusar ese metodo y crear el ticket de autenticacion de forma concreta y luego usar el Response.Redirect()
o sea usarias el
FormsAuthenticationTicket (Clase)
saludos
Muchas gracias Leandro, pero asumiendo que eso lo hago en el formulario de login; donde especifico el webform al que quiero se redirija cuando me loguee??
ResponderEliminares decir, yo quiero que al logearme me redirija al form que está en "Management/menu.aspx"
pero en el metodo no veo en donde le indico que se vaya a esa direccion...
Saludos y gracias :)
hola EddieF
ResponderEliminarsi usas la seguridad de asp.net esto lo defines en el web.config, en la config defines a que pagina se debe redireccionar
no es en el metodo donde lo defines, es en la configuracion
saludos
Hola, Leandro si ya tengo implementado tu ejemplo en asp.net
ResponderEliminarcomo hago para configurar las opciones del menu por usuario,
digamos que a un usuario no quiero que accese a la opción de ventas del menu que se ponga Ventas Enable=false..Saludos
hola manuel
ResponderEliminarpodrias poner el enabled en false para ese item del menu, pero deberias definir algun rol
entonces sabiendo el rol podrias aplciar logica que habilite o no el item del menu
saludos
Buen tutorial Leandro, una pregunta; como podria validar que un usuario solo pueda estar logueado una sola vez, si intentan logearse desde otra maquina con el mismo usuario que esta activo.
ResponderEliminarSaludos
hola Pit
ResponderEliminarel tema es que al estar en un ambiente web no es facil de lograr
aqui
http://social.msdn.microsoft.com/Forums/en-US/b7d7e8f1-ca9b-4915-965a-9dab12310f9d/evitar-sesiones-mltiples-de-un-mismo-usuario-en-una-aplicacin-web
se plantea lo mismo
saludos
Hola Leandro, como hago para aplicar esto de la inserción en un proyecto asp.net mvc, solo es que me lo expliques no pido ningún codigo
ResponderEliminarAtt: JYag
Hola Leandro, como hago para realizar la insercion en asp.net mvc, solo pido una explicacion...al aplicar el autenticar me dio perfecto y es mas que lo realice con busquedas del usuario en varias bases de datos
ResponderEliminarHola Leandro, una pregunta con el tema de usuarios.. estoy trabajando en 3 capas,, y la unica solucion rapida que pude encontrar por ahora es declarar una variable global dentro de un modulo para guardar el usuario. Segun lei no es recomendado. Este modulo lo coloque dentro de la capa de entidades para que sea visible en todas las capas.. Conoces otro metodo de almacenar un usuario y que sea visible por todas las capas? Gracias..
ResponderEliminarhola Joe NUÑEZ
ResponderEliminarlo que no entendi es a que inserción haces referencia, apuntas al insert que se realiza en la tabla del usuario ?
porque ese es codigo ado.net simple, el cual imagino deberias implementar en alguna clase en otro proyecto del tipo class librar y desde el action de algun controlador invocarlo
saludos
hola Si Señor
ResponderEliminarpodrias implementar una clase singleton que dentro utilice un objeto Session
com se planteo aqui
http://social.msdn.microsoft.com/Forums/es-ES/10bbbd6a-b8f5-4b43-bb2b-778341ac01f0/singleton-en-varias-capas
de esta forma desde la UI asignas el valor y podrias tomarlo desde otras capas
saludos
Hola Leandro, me olvide de decirte que el tema del usuario era para una aplicación de escritorio.. Gracias..
ResponderEliminarhola Si Señor
ResponderEliminarentonces es mas simple
aplcias el mismo concepto de singleton solo que no necesitas al objeto Session, sino que usas directo una variable
algo como esto
http://ltuttini.blogspot.com.ar/2011/07/winforms-singleton-pasar-datos-entre.html
solo que tu usaras esa clase tambien desde otros proyectos
Nota: esto lo vas a tener que implementar en un proyecto separado para asi poder referenciarlo desde los demas proyectos (otras capas) que necesiten de la info
saludos
Hola Leandro, me funciono perfecto lo del singleton. Lo que hice fue hacer lo del singleton y agregue una propiedad de usuarioLogueado y en login le asigno el usuario. una pregunta:
ResponderEliminar1)cual es la diferencia entre crear un singleton + la propiedad en crear una clase sin el singleton pero con la propiedad? osea cual es el objetivo del singleton.
Saludos
hola Si Señor
ResponderEliminarel patron singleton tiene por objetivo devolver la misma instancia para todo aquel que lo invoque
por lo que lo convierte en un patron ideal como punto central donde poner informacion global, lo bueno es que como utilizas objetos puedes implementar info mas compleja en funcionalidad comparado con tener solo una simple variable public y static
saludos
eres el amo de .net!! saludos!!
ResponderEliminarHOLA Leandro mira el punto es que necesito que me ayudes a hacer una encriptacion de mi contraseña con hash pero estoy utilizando MVC de Asp.net y SQL Server 2012
ResponderEliminarhola Carlos
ResponderEliminarpero en este mismo ejemplo muestro como implementar un hash para la contraseña, en mvc es exactamente igual, y la db tampoco afecta
saludos
Pero en que parte tengo que colocar ese codigo
ResponderEliminarhola Carlos
ResponderEliminaranalizaste el codigo del articulo ?
porque alli muestro donde lo utilizo
cuando creas un nuevo usuario, o cuando vayas a validar, en ambos casos tomas lo que el usuario ingresa en los controles y aplicas el hash
saludos
Hola Leandro, implemente tu ejemplo en mi proyecto y funciono de 10.
ResponderEliminarahora te queria pedir si me podes ayudar a implementar roles para aplicar la seguridad en las paginas de mi proyecto.
los accesos/permisos a las paginas las quiero tener en la base de datos y no en el web.config, como debo hacer?
hola anibal
ResponderEliminarpodrias crear una table de roles y otra de funciones
las funcioens dirian algo como ser "leer articulos", "editar proveedor", etc
o sea que funcion cumple, estas funciones se agruparian en los roles, entocnes un rol tendria N funciones
a los usuario le asignas el rol por lo que tendria un grupo de funciones que usarias en tu codigo para poder saber si puede realizar una determinada accion, esto lo implementas en el codigo con logica que valida si para ahcer determinada accion dispone de esa funcion
saludos
gracias Leandro, lo que hice hasta ahora es el login, y guardar perfil y permisos del usuario en cookies, mi duda es como hago para leer de esas cookies en cada pagina.
ResponderEliminarvi este ejemplo(http://msdn.microsoft.com/es-es/library/bb972205.aspx), pero no me andan las interfaces que utiliza, esta bien utilizar modulos o deberia usar otra cosa? gracias!!!
hola anibal
ResponderEliminarla verdad ese articulo es un poco antiguo, no creo que usar un handler para implementar seguridad sea lo correcto
por eso existe asp.net membership
Custom MembershipProvider Y RoleProvider
puse el link de una implementacion custom porque en este caso dwefines una estructura diferente a la estandar
saludos
gracias, voy a revisarlo...
ResponderEliminarestoy en un proceso de asimilacion de estas herramientas.
Saludos!
Hola muy bueno tu articulo, si sabes...me podrías decir cuál sería una manera "segura" de restringir paginas (ya tengo roles),pero sin usar cookies y no estar haciendo consultas a la BD cada momento. ?
ResponderEliminarhola ethnox
ResponderEliminaren asp.net el acceso a las paginas no esta limitado, si podrias definir en el config el tag he indicar que rol o si se requiere autenticacion para una pagina o carpeta dentro del sitio
podrias tambien unir el rolProvider con el sitemap para que algun menu muestre o no los link de acceso a las paginas
http://social.msdn.microsoft.com/Forums/es-ES/17190ffc-a8a2-4e9d-9282-572f05ec817f/como-habilitar-elementos-del-menu-segun-rol-con-aspnet-y-c
http://social.msdn.microsoft.com/forums/es-ES/ff76b43a-9be8-42a8-9eec-9e353517a9ee/dar-permisos-para-usuario-en-menus-aspnet
http://social.msdn.microsoft.com/Forums/es-ES/e38aa8fd-7b77-4fd7-8c64-25168ed44e75/web-sitemap-con-un-role-provider-personalizado
saludos
Hola Leandro.
ResponderEliminarMe gustaría que me aconsejaras que método de encriptación usar para guardar contraseñas de los usuarios.
Ya que no paro de leer que MD5 y SHA-1 no son aconsejables.
¿Qué método recomiendas para encriptar passwords?
Un saludo y gracias.
hola misretoques
ResponderEliminarcomo que el hash no es aconsejable, es justamente lo que debes usar para aplicar la mejor seguridad en el password del usuario
en este articulo justamente uso estos para que nadie pueda obtener la contraseña
saludos
Hola leandro, una pregunta.. me muestra error en la linea "UsuarioEntity usuario = new UsuarioEntity();" y en la linea "SHA1 sha1 = new SHA1CryptoServiceProvider();"
ResponderEliminara qué puede deberse? desde ya gracias! excelente post
hola Mily
ResponderEliminarcual es el mensaje de error que recibes ?
este se produce al compilar o cuando ejecutas la aplicacion?
saludos
Para la linea: "UsuarioEntity usuario = new UsuarioEntity();" me muestra el siguiente error de compilación:
ResponderEliminar"No se puede encontrar el tipo o el nombre de espacio de nombres 'UsuarioEntity' (¿falta una directiva using o una referencia de ensamblado?)"
y para la línea: "SHA1 sha1 = new SHA1CryptoServiceProvider();" me muestra el siguiente error de compilación:
"No se puede encontrar el tipo o el nombre de espacio de nombres 'SHA1' (¿falta una directiva using o una referencia de ensamblado?)"
hola Mily
ResponderEliminarvalidaste que esten las referencias al proyecto de entidades ? y que la definicion del "using" donde defines el namespace de esta entidad este bien definido
es mas si realizas una busqueda por UsuarioEntity en la solucion se encuentra esta clase definida ?
para SHA1 recuerda que esta en el namespace System.Security.Cryptography por lo que deberias definirlo en el using
saludos
Excelente ejemplo, pero tengo una pregunta, ¿cómo puedo hacer para que un usuario pueda tener solo una sesión iniciada? Es decir, si intenta iniciar sesión en otra máquina cuando ya tiene una sesión iniciada le niegue el acceso, y ¿cómo poder controlar para que las sesiones no se queden "colgadas" en caso de que no pongan "logout"?
ResponderEliminarhola Sergio
ResponderEliminarno lo veo facil de lograr, la verdad nunca he implementado algo similar pero imagino deberias mantener la info de los usuario que estan activos en el objeto Application para que sea global al sitio web
podrias validar alli si el usuario ya se autentico, quizas si por alguna razon no pasa por el Session_End para quitarlo de la lista, adicionalmente se podria crear alguna funcionalidad de admin para que alguien pueda removerlo en caso de quedar alli registrado, aunque igualmente al vencer la session a los 20min se deberia remover solo
por supuesto si el sitio se reinicia el application se perdera, pero igual es algo temporal
saludos
Primero que nada Muchas Gracias por todos tu ayuda, ami me han ayudado un buen tus ejemplos. en este caso solo quiesiera si me pudieras ayudar a conectarla a una base de datos externa, que no se encuentre en el mismo poryecto, ya trate y trate y no he podido. Espero que me ayudes.
ResponderEliminarGracias!!
hola Jose
ResponderEliminarcomo defines el connection string? porque si la db esta en una pc diferentes solo haria falta especificar en el DataSource el nombre o la ip de esa pc
recuerda tambien validar que el firewall de windows no este bloqueando la conexion
y si usas un sql express de habilitar el servicio para poder recibir coneciones remotas, ya que por defecto solo las permite locales
saludos
Leandro, gracias por tu respuesta, ya lo adapte, el siguiente problema fue al momento de guardar no se pudo, pero lo intente de otra manera y ya quedo,, gracias!!!
ResponderEliminarLeandro referente a tu artículo escrito "Login - Usando Password con Hash", ¿Qué pasa si en el botón cancelar del loginUI agrego una confirmación si realmente desea salir del sistema? lo hice, pero al presionar el botón "NO" en la confirmación, igual se cierra el sistema, ¿Me podrías ayudar con eso?
ResponderEliminarSaludos y gracias
hola Daniela
ResponderEliminarpero esta validacion la realizas en el evento formclosing del form ?
si es asi al cancelar el dialog estas asignando el e.Cancel para que anule el cierre
Form.Closing Event
saludos
Mira en el frmLogin_FormClosing tengo esto
ResponderEliminarprivate void frmlogin_FormClosing(object sender, FormClosingEventArgs e)
{
switch (e.CloseReason)
{
case CloseReason.FormOwnerClosing:
e.Cancel = true;
break;
//Si se deja este 'caso', no permite entrar cuando se presiona el botón Ingresar.
case CloseReason.None:
e.Cancel = true;
break;
case CloseReason.TaskManagerClosing:
e.Cancel = true;
break;
case CloseReason.UserClosing:
e.Cancel = true;
break;
case CloseReason.WindowsShutDown:
e.Cancel = true;
break;
}
}
y luego en el botón cancelar tengo esto
private void btnCerrar_Click(object sender, EventArgs e)
{
DialogResult Resultado = MessageBox.Show("¿Está seguro que desea salir?", "Confirmación", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (Resultado == DialogResult.Yes)
{
Application.Exit();
}
}
hola Daniela
ResponderEliminaren el evento del cancelar no pones ningun mensaje, lo debes poner en el formclosing
private void frmlogin_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult Resultado = MessageBox.Show("¿Está seguro que desea salir?", "Confirmación", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (Resultado != DialogResult.Yes)
{
e.Cencel = true;
}
}
private void btnCerrar_Click(object sender, EventArgs e)
{
this.Close()
}
no se lo del switch de las razones de cerrar el form, peor la pregunta se realiza en el evento de cierre para anularlo si es que se selecciona esto en el messagebox
saludos
hola leandro un saludo desde peru, como puedo recuperar el usuario ,en otros formularios oseo si es usurio q inicia seccion como puedo recuparar a ese usuario en cualquiero formulario
ResponderEliminarhola Deyvi
ResponderEliminarpodrias usar la tecnica
[Winforms] Singleton - Pasar datos entre formularios
para asi poner el usuario en el singleton global al cual puedes acceder desde cualquier form
saludos
hola, para comenzar con esta aplicacion debemos crear una aplicacion normal de windows form cierto?
ResponderEliminarEric
ResponderEliminarexacto, luego si lo necesitas a la solucion le vas agregando otros proyecto, peor inicias con un Windows Application
saludos
Hola Leandro,
ResponderEliminarUn gusto saludarle,
Tengo una duda, me preguntaba si hay alguna diferencia en cifrar los datos desde el Sql Server, y con este método con el que tu haces.
En esta página:
http://msdn.microsoft.com/es-es/library/bb972194.aspx
En la página se dice que hay 4 formas de cifrar los datos, uno con más segurida que el otro, pero con más uso de recursos.
hola Miguel
ResponderEliminarel tema por lo que veo es que la seguridad en sql server esta generando claves simetricas o publica-privada, por lo que de alguna forma es posible consiguir nuevamente el dato de la db
lo que yo planteo implica no poder volver hacia atras, el hash solo va en una direccion, por eso aplicas el hash y comparas con lo que tienes en la db, no hay password ni claves que permitan volver a obtener el valor original que el usaurio puso como clave de su login de ingreso
si desde sql server puedes aplicar hash entonces realizalo seria lo mismo
esto lo planteo para autenticacion, ahora si es para otro tipo de datos de negocio eso es otro tema
saludos
Leandro muchas gracias, me ha servido mucho. Pero me queda una duda. Tengo un gridview, y en la parte de la contraseña que es el siguiente:
ResponderEliminarAl hacer clic para actualizar los datos, si actualizo el campo contraseña no hay problema, pero si actualizo cualquier otro campo y no hago nada en el campo contraseña, esta no se mantiene, o sea toma el valor de este Text="****", y realiza el hash con "****". Cómo puedo hacer para que, si no quiero actualizar la contraseña pero si otro campo, la antigua contraseña se mantenga? y no se cambie por otros valores?
Muchas muchas gracias!
Leandro muchas gracias, me ha servido mucho. Pero me queda una duda. Tengo un gridview, y en la parte de la contraseña que es el que la tengo dentro de un templatefield
ResponderEliminarAl hacer clic para actualizar los datos, si actualizo el campo contraseña no hay problema, pero si actualizo cualquier otro campo y no hago nada en el campo contraseña, esta no se mantiene, o sea toma el valor de este Text="****", y realiza el hash con "****". Cómo puedo hacer para que, si no quiero actualizar la contraseña pero si otro campo, la antigua contraseña se mantenga? y no se cambie por otros valores?
Muchas muchas gracias!
hola Patricio
ResponderEliminarpor lo generar se definen dos form, uno para editar todos los datos del usuario (menos la contraseña) y otro adicional para cambiar el password (serian el tipico form que piden ingresar la contraseña actual y repetir dos veces la nueva)
entonces cuando creas el usuario pides todos los datos incluyendo la contraseña
pero cuando actualizas la contraseña no la pides, ya que tiene el otro form para el cambio de contraseña
saludos
HOLA LEANDRO, quisiera utilizar esa validacion medicante un webmethod
ResponderEliminarpero me sale error al ejecutar el
FormsAuthentication.RedirectFromLoginPage
este es el codigo..
Public Shared Sub validar(ByVal usuario As String, ByVal contrasena As String)
If Autenticar(usuario, contrasena) Then
FormsAuthentication.RedirectFromLoginPage("xxx", False)
Else
'ErrorMessage.InnerHtml = "Usuario o contraseña incorrectos... por favor re-ingrese las credenciales..."
End If
hola Maicol8k
ResponderEliminarse respondio en el foro
como ejecutar FormsAuthentication.RedirectFromLoginPage desde webmethod
saludos
Hola Leandro,estoy tratando de adaptarlo tu ejemplo con mi ide de visual y sql server 2012.El web form lo puedo ver sin problema en el navegador,pero como hago para establecer la conexion con la bd, o en que parte puedo verla como esta compuesta la bd para crear las tablas aparte y establecer la nueva conexion en el app.config?
ResponderEliminarhola Andres
ResponderEliminarsi el desarrollo es web deberias revisar el web.config
alli estara la conexion definida
en este caso como no uso el proveedor de asp.net membership puede poner las tablas juntos al resto, no necesitas separarlo
saludos
Que tal
ResponderEliminarme esta sirviendo mucho tu codigo
Tanto que quiero implementarlo en mi proyecto pero necesito hacerlo con procedimientos almacenados como se implementaria la validacion en sql y como lo implementaria en visual basic
hola Anthony
ResponderEliminarpero conoces como crear stored procedure ?
porque en este caso seria tan solo pasar las consulta y definir en el SqlComand el CommandType indicando que es un procedure
en el articulo se puede descargar el codigo en vb.net
saludos
Este comentario ha sido eliminado por el autor.
ResponderEliminarHola, excelente y muy explicado todo, sin embargo necesito hacer lo siguiente, si me pudiera ayudar sería perfecto:
ResponderEliminarDebo almacenar un valor llamado cod_cia, el cual debe permanecer siempre desde que se inicia la sesión, hasta que se cierra.
Cual es la manera más recomendada para esto? Actualmente lo hago con variable Session
Hola leandro una pregunta , este codigo lo puedo definir en el master page o tengo que hacerlo pagina por pagina
ResponderEliminarHola Leandro, muy buen tutorial, sin embargo tengo un problema con una aplicación winforms. Estoy tratando de llamar desde el Main() mi formulario Login antes del principal, de la sig manera:
ResponderEliminarApplication.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Login login = new Login();
login.ShowDialog();
if (login.DialogResult == DialogResult.OK)
{
Application.Run(new HomeStudent());
}
Cuando el usuario es validado correctamente, hago lo siguiente para que entre en la condición del Main():
this.DialogResult = System.Windows.Forms.DialogResult.OK;
Pero al hacer el cambio de formularios mi aplicación se cierra por completo, estoy pasando algo por alto? Estoy utiliando VS2012 y la versión 4.5 del .NET Framework.
Un saludo
Mario
hola
EliminarQue seria el cambio de formulario ?
Recuerda que si haces un close del HomeStudent la aplicacion se va a cerrar, porque esta es la que defines como inicial
saludos
Listo Leandro, había olvidado que tenía un evento Closing en el form Login, por lo tanto se cerraba la aplicación cuando cambiaba el valor de la propiedad DialogResult.
EliminarUn saludo!!
hola leandro prodias verificar que le falta mi codigo que cuando me logeo no ingresa a la pagina principal ..
ResponderEliminarusing System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Web.Configuration;
namespace Sistema_ProcePeso
{
public class Datos
{
public static bool Autenticar(string usuario, string password)
{
string sql = @"SELECT COUNT(*)
FROM ma_usuarios
WHERE login_name = @nombre AND Password = @password";
using (SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["default"].ToString()))
{
conn.Open();
SqlCommand command = new SqlCommand(sql, conn);
command.Parameters.AddWithValue("@nombre", usuario);
string hash = Helper.EncodePassword(string.Concat(usuario, password));
command.Parameters.AddWithValue("@password", hash);
int count = Convert.ToInt32(command.ExecuteScalar());
if (count == 0)
return false;
else
return true;
}
}
------------------------------------------------ Este de la clase loginservice-----------------------
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
namespace Sistema_ProcePeso
{
public class LoginService
{
public static bool Autenticar(string usuario, string password)
{
string sql = @"SELECT COUNT(*)
FROM MA_USUARIOS
WHERE NombreLogin = @nombre AND Password = @password";
using (SqlConnection conn = new SqlConnection("Data Source=localhost;Initial Catalog=VAD10;Persist Security Info=True;User ID=sa;Password=123456;"))
{
conn.Open();
SqlCommand command = new SqlCommand(sql, conn);
command.Parameters.AddWithValue("@nombre", usuario);
string hash = Helper.EncodePassword(string.Concat(usuario, password));
command.Parameters.AddWithValue("@password", hash);
int count = Convert.ToInt32(command.ExecuteScalar());
if (count == 0)
return false;
else
return true;
}
}
}
}
}
}
hola
EliminarPara que defines la clase "Datos" si despues tienes el mismo codigo en la clase "LoginService" ?
Se supone que la capa de servicio deberias hacer uso de la capa de datos, pero no se repite el codigo
saludos
Hola leandro, veo que tu post es del 2010 y aun pasando 5 años me ha ayudado para mi aplicacion. Muchas Gracias!!!
ResponderEliminarHola Leandro:
ResponderEliminarUna consulta. Luego del Login, como se podría hacer para que en algún formulario distinto de la aplicación se pueda saber qué usuario esta Logeado? Por ejemplo si dicho usuario realiza una modificación enviar el usuario como parámetro a otra tabla de la base de datos?
hola leandro, muy bueno tu blog, una consulta, tengo un proyecto de ejemplo creado en visual studio 2008 SP1 y tengo diferentes paginas default, default2, default3, login, no tengo masterpage, la pagina 1 tiene un link que me redirecciona a la pagina 2 y la 2 un link que me redirecciona la pagina 3, pero cuando cierro sesión 3 al darle atras en el botón de navegacion de mi navegador al principio si me presenta la de login, pero conforme le voy dando click para atras en el boton del navegador ya me presenta las paginas 3, 2 y no se queda en la de login espero tu ayuda saludos
ResponderEliminar