Validar Credenciales con sqlMembershipProvider

Autor: Osmar 7. enero 2011 09:51

Como validar credenciales de usuarios usando data en sqlMembershipProvider  

(sqlMembershipProvider part #3)

En terminos generales, en las aplicaciones web que usan autentificacion por “Form”, un usuario ingresa a la aplicacion  visitando la pagina “login” e ingresando sus credenciales, las cuales son comparadas con las que se tienen almacenadas. Si son validas el usuario logra una “entrada” de autenticacion (“forms authentication ticket”), el cual es una “ficha” (“token”) de seguridad que indica la identidad y autenticidad del visitante.

Para validar el usuario frente al “Membership Framework”, debemos usar el metodo ValidateUser. El metodo “ValidateUser” toma dos parametros de ingreso – username y password – luego devuelve un valor logico (“Boolean”) que indica si la credencial fue valida o no. El metodo ValidateUser delega la validacion a la configuracion que se haya hecho del “Proveedor de Membresia” (“Membership provider”).

El SqlMembershipProvider valida las credenciales sumistradas obteniendo el password del usuario via el “stored procedure” aspnet_Membership_GetPasswordWithFormat. Recuerde que el password, en SqlMembershipProvider, usa una de las tres formas: Clear, Encrypted, o Hashed. El “stored procedure” aspnet_Membership_GetPasswordWithFormat devuelve el password en su forma “cruda” (“raw”), major dicho como lo encuentra en el almacen de data (la base de data en este caso). Para passwords encriptados o “hashed”, El SqlMembershipProvider transforma el password suministrado, remitido como parametro en el metodo “ValidateUser”, en su equivalente encriptado o hashed (segun sea el caso), y luego lo compara con los valores que han sido recuperados de la base de datos. Si el password almacenado en la base de datos coincide con el password formateado (encriptado o hashed)  ingredado por el usuario, la credencial es validad.

Podemos crear una pagina (~/Login.aspx) que contenga una interface con dos TextBoxes para el “username y password”, un “Remember Me” checkbox, y un boton Login (como en la siguiente figura y el “design” modo se vera asi, de acuerdo a tu Master Page).

 

Para la validacion de las credenciales debemos programar el evento click (“Click event handler”) del boton Login (en modo de “design” puedes hacer doble click en el boton “Login”):

protected void LoginButton_Click(object sender, EventArgs e)
{
 // Validate the user against the Membership framework user store
 if (Membership.ValidateUser(UserName.Text, Password.Text))
 {
 // Log the user into the site
 FormsAuthentication.RedirectFromLoginPage(UserName.Text, RememberMe.Checked);
 }
 // If we reach here, the user's credentials were invalid
 InvalidCredentialsMessage.Visible = true;
}

 

 

El codigo es simple, comenzamos llamando al metodo Membership.ValidateUser, pasando los valores del username y password que hay en los “texBoxes”. Si el metodo devuelve un valor “true”, entonces el usuario ingresa a la aplicacion (“sign in”) via la clase “FormsAuthentication” y su metodo “RedirectFromLoginPage”. El FormsAuthentication.RedirectFromLoginPage  crea el “boleto” (“ticket”) de autenticacion (“forms authentication ticket”) y redirecciona al usuario a la pagina apropiada (De acuerdo a los seteos que se hayan realizado). Si la credencial es invalida, la etiqueta “InvalidCredentialsMessage” es mostrada e informa al usuario que el “username” o “password” fueron incorrectos.

Y, Ya no ya!!, esa seria la version simple para nuestra pagina de login.

Nota: Las credenciales del usuario (incluyendo el password) son trasmitidas por internet via texto plano (“plain text”). Eso significa que cualquier hacker que este “husmeando” ("sniffing”) podra ver el username y password. Para evitar esta situacion se puede encriptar el trafico del sitio usando Secure Socket Layers (SSL).

 

Como “Membership Framework” maneja los intentos invalidos?

Cuando un visitante esta en la pagina de login y remite sus credenciales, el browser hace un requerimiento HTTP  a la pagina de login. Si las credenciales son validas, la respuesta HTTP incluye el “ticket” de autentificacion en un cookie. Por consiguiente un “hacker” (pirata filibustero contemporaneo) que intente quebrar la seguridad de tu sitio, podra crear un programa que exhaustivamente envie HTTP requests a la pagina de login con un username valido y tratando de adivinar el password. A traves del metodo de “Fuerza Bruta” (“Brute Force”), el cual se raliza con un programa, podrian “adivinar” o encontrar el password, en especial si este tiene una estructura debil (facil de adivianr con diccionario).

Para preveer el uso de “fuerza bruta”, el “Membership framework” blockea a un usuario si existe un numero determinado de intentos no exitosos en un periodo de tiempo. Para esto se setean los parametros:

  • maxInvalidPasswordAttempts – que especifica cuantas veces de intentos con password invalidados se puede permitir, luego de los cuales la cuenta es bloqueada. El valor por defecto es 5.
  • passwordAttemptWindow – Indica el tiempo en minutos durante el cual se puede intentar el numero espcificado de intentos fallidos de ingresar al sistema. El valor por defecto es 10 minutos.

Nota: Si un usuario ha sido bloqueado, no podra ingresar a la aplicacion hasta que el administrador desbloquee la cuenta. Debe considerar que cuando la cuenta de un usuario esta bloqueada, el metodo “ValidateUser” siempre retorna un valor falso (false), aun si las credenciales son validas.

Desafortunadamente no hay una herramienta incluida (“built-in”) que ayude a desbloquear una cuenta. El campo IsLockedOut en la tabla aspnet_Membership debe ser cambiado manual o con un programa (obviamente recomendamos la segunda forma).

Recolectando Credenciales usando el Control Web Login

El web control “Login” nos ahorra el trabajo de tener que crear una interfase que permita tomar las credenciales del usuario. Este web control Login permite al usuario ingresar o ser rechazado automaticamente a la aplicacion sin escribir codigo.

Si has creado alguna pagina de Login.aspx podrias comentar (<%--  --%>) el HTML creado y reemplazarlo con el web control “Login” (como nos ejercitamos en la seccion anterior).

 

Para colocar el web control en tu pagina, arrastra el control Login desde el “Toolbox” a tu pagina y nombra la propiedad ID como “myLogin”. Tu pagina se vera similar a la siguiente figura. Nota que por defecto el control incluye controles TextBox para username y password, un “Remember me next time” CheckBox, y un “Log In” Button. Tambien hay controles de RequiredFieldValidator para los dos TextBoxes.

 

El control “Login” usa 4 factores para determiner la “apropriada pagina” a donde re-direccionar (“redirect”) al usuario en un “log in” satisfactorio:

  • Si el web control “Login” esta en la pagina de “login”, el destino esta definido por el loginUrl en la configuracion de la autentificacion del form; por defecto este setting es Login.aspx
  • La presencia de un parametro querystring ReturnUrl
  • El valor de la propiedad DestinationUrl  del control “Login”
  • El defaultUrl especificado en los seteos de configuracion del “forms authentication”; por defecto este valor es Default.aspx

En la siguiente figura se muestra como el control Login usa estos 4 parametros para llegar a su pagina destino apropiado.

 

Personalizando la apariencia del Web Control Login

El web control Login por defecto devuelve una interfase de usuario con el titulo de “Log In”, una etiqueta y TextBox para el “username” ,  una etiqueta y TextBox  tambien para el “password”, un “Remember me next time” CheckBox, y un  boton “Log In”. La apariencia de estos elementos son configurables a traves de varias propiedades del web control Login, adicionalmente un link a una pagina para crear una nueva cuenta de usuario puede ser agregada seteando una o dos propiedades.

En la pagina Login.aspx el texto en la parte superior de la pagina “Login” puede ser establecido (“seteado”) con la propiedad TitleText.

La etiquetas “User Name:” y el “Password:” a la izquierda de los TextBox pueden ser personalizados con las propiedades UserNameLabelText y PasswordLabelText, respectivamente. Cambiemos “User Name:” a “Username:”. El estilo de las etiquetas pueden configurarse a traves de las propiedades  LabelStyle y TextBoxStyle properties, respectivamente.

El texto de la propiedad “Remember me next time” CheckBox’s puede ser establecida (“seteada”) a traves del la propiedad RememberMeText, y su estado de estar marcada (“checkeada”) o selecionada es configurable a traves de la propiedad RememberMeSet que por defecto es “False”. Si estas caminando conmigo (trabajando en esto) establece (“Setear”) la propiedad “RememberMeSet” a “True” y  el asi que el CheckBox “Remember me next time” aparecera como marcado (checked) o “palomeado como dirian los mexixanos.

Este web control ofrece dos propiedades para definir la distribucion (“layout”) de la interfase de usuario. La propiedad TextLayout indica si las etiquetas el “Username:” y “Password:” aparecen a la izquierda de su correspondiente TextBoxe (valor por defecto), or arriba de ellos. Por otro lado, la propiedad de orientacion Orientation indica si los texboxes username y password estaran de manera vertical (uno encima de otro) u horizontalmente. Estamos dejando estas dos propiedades por defecto, pero recomendamos que trates de “setear” estas dos proopiedades a valores no por defecto par aver el resultado de la apariencia.

El web control “Login” puede tambien contener un mensaje con un link para enrolarse en la aplicacion (“sign up” o crear usuario) usando las siguientes propiedades CreateUserText y CreateUserUrl a “Not registered yet? Create an account!” y “~/Membership/CreatingUserAccounts.aspx”,  respectivamente. Esto agrega un hyperlink a la interfase de usuario del control “Login” que apunta a la pagina para crear un usuario (ver entrada en esta categoria correspondiente a Como Crear Un Usuario en este mismio sitio). De la misma manera se puede agregar mas facilidades a los usuarios como una pagina de ayuda y un link para recuperacion de passwords a traves de las siguientes propiedades HelpPageText , HelpPageUrl , PasswordRecoveryText y PasswordRecoveryUrl.

Si se hacen los cambios respectivos para estas propiedades, nuestra pagina podria verse asi:

 

Aumentando mas credenciales al Web Control Login (Login super seguro).

Por defecto el Web Control Login genera un tag HTML <table>. Pero podemos reemplazar este tag con una serie de tags <div>. Si la aplicacion require mas credenciales para la autentificacion, como se estila en algunos sitios financieros, es possible convertir el control Login en un template (plantilla), para lo cual debemos definer explicitamente el codigo HTML (markup).

Para recolectar credenciales adicionales debemos hacer 2 cosas:

  1. Actualizar la interfase del control “Login” para incluir las credenciales adicionales.
  2. Sustituir la logica interna del control Login para que el usuario sea autentificado solo si su username, password y sus adicionales credenciales son validas.

Para el numeral 1, necesitamos convertir el web control en un “template” y agregar los controles necesarios. Para el numeral 2, la logica de autentificacion debera ser sustituida creando un manejador de evento (“event handler”) para el evento Authenticate.

Actualizemos el control que nos permita ingresar username, password, y  “email address” y solo autentifica si el email address suministrado coincide con el email address en la base de datos. Primero convertimos el control en un”template”, para esto desde el control Login en el Smart Tag, escojemos la opcion “Convert toTtemplate” (ver figura de abajo)

 

Luego de Convertir el control a template, VS agrega el LayoutTemplate en el markup HTML. Como se muestra en la siguiente figura, tambien debe eliminarse algunas propiedades que no se usan en un template como: TitleText, CreateUserUrl, y otras mas.

 

El markup HTML en el LayoutTemplate puede ser modificado segun la necesidad. Sin embargo es necesario mencionar que el nucleo del web control Login debe permanecer, asi como el ID. No elimine o renombree los controles UserName o Password TextBoxes, el RememberMe CheckBox, el LoginButton Button, el FailureText Label, o el  RequiredFieldValidator.

Para colectar el email address del visitante, necesitamos agregar un TextBox al  template. Agregar el siguiente codigo a la fila(<tr>) que contiene el Password TextBox y la fila de la table donde esta el “Remember me next time” CheckBox:

<tr>
 <td align="right">
 <asp:Label ID="EmailLabel" runat="server" AssociatedControlID="Email">Email:</asp:Label>
 </td>
 <td>
 <asp:TextBox ID="Email" runat="server"></asp:TextBox>
 <asp:RequiredFieldValidator ID="EmailRequired" runat="server" 
 ControlToValidate="Email" ErrorMessage="Email is required." 
 ToolTip="Email is required." ValidationGroup="myLogin">*</asp:RequiredFieldValidator>
 </td>
</tr>

 

 

 

Modificando la logica de autentificacion del Web Control Login

Cuendo un visitante ingresa sus credenciales y hace click en el boton “Log In”, sucede un “postback” y el control Login incia el proceso de autentificacion. El proceso incia con el evento LoggingIn. Cualquier manejador de eventos (event handlers) asociado con este evento puede cancelar la operacion seteando la propiedad e.Cancel a “true”.

Si la operacion no es cancelada el proceso continua iniciando el evento Authenticate. Si hay un manejador de evento para el evento Authenticate, entonces este es responsable por determiner si las credenciales suministradas son validas o no. Si no hay un manejador de eventos el controlador usa el metodo “Membership.ValidateUser”  para determinar la valides de las credenciales.

Si las credenciales son validas un ticket de autentificacion es creado y se inicia el evento LoggedIn , y el usuario es redirecionado a la apagina apropiada. Si las credenciales son invalidads el evento LoginError es iniciado y un mensaje informativo es mostrado. En caso de credenciales invalidas, por defecto el mensaje es: (“Your login attempt was not successful. Please try again”). Sin embargo si la propiedad FailureAction es setada a RedirectToLoginPage, el control genera un Response.Redirect a la pagina de login agregando el parametro querystring loginfailure=1 (el cual causa que el control Login muestre el mensaje de error).

Como crear un Manejador de Eventos (Event Handler) para la autenticacion.

Si necesitaramos una secuencia logica personalizada o ajustada a nuestra medida de autentificacion debemos crear un Manejador de Eventos (“event handler”) para el evento de autentificacion:

protected void myLogin_Authenticate(object sender, AuthenticateEventArgs e) { }

Como vemos, el “event handler” pasa un objeto de tipo AuthenticateEventArgs como su segundo parametro. La clase AuthenticateEventArgs contiene una propiedad logica (Boolean) llamada Authenticated que es usada especificamente si las credenciales suministradas son validas. Por ello, nuestra tarea es escribir codigo que permita validar las credenciales suministradas y setear la propiedad e.Authenticate de manera adecuada.

Validacion de las crednciales suministradas

Las propiedades UserName y Password permiten tomar las credenciales de username y password ingresadas por el usuario. Para determiner el valor ingresado en cualquier control adicional  (tales como el Email TextBox que agregamos anteriormente), usamos  LoginControlID.FindControl("controlID") para obtener programaticamente una referencia del control en el template cuya ID property es igual al controlID. Por ejemplo para obtener la referencia del Email TextBox, usamos el siguiente codigo:

TextBox EmailTextBox = myLogin.FindControl("Email") as TextBox;

Para validar las credenciales del usuario necesitamos dos cosas.:

  1. Asegurar que el username y password suministrados son validos
  2. Asegurar que el email address coincide con el email address en la base de datos de ese usuario.

Para asegurar que el username y password suministrados son validos, solo es necesario usar el metodo “Membership.ValidateUser”. Para la segunda tarea necesitamos determiner el email address del usuario y compararlo. Para tener la informacion de ese usuario en la base de datos usamos el metodo GetUser.

El medoto GetUser tiene varias formas de ser llamado. Si se usa sin parametros logramos datos del usuario que esta logeado. Para informacion de un usuario determinado es neceario pasar el username. En cualquier caso este metodo regresa un objeto MembershipUser, el cual tiene propiedades como UserName, Email, IsApproved, IsOnline, y otras mas.

En el siguiente codigo podemos ver estas dos validaciones, si las dos son validas el e.Authenticate toma el valor “true”, en caso contrario su valor es “false”.

protected void myLogin_Authenticate(object sender, AuthenticateEventArgs e)
{
 // Get the email address entered
 TextBox EmailTextBox = myLogin.FindControl("Email") as TextBox;
 string email = EmailTextBox.Text.Trim();

 // Verify that the username/password pair is valid
 if (Membership.ValidateUser(myLogin.UserName, myLogin.Password))
 {
 // Username/password are valid, check email
 MembershipUser usrInfo = Membership.GetUser(myLogin.UserName);
 if (usrInfo != null && string.Compare(usrInfo.Email, email, true) == 0)
 {
 // Email matches, the credentials are valid
 e.Authenticated = true;
 }
 else
 {
 // Email address is invalid...
 e.Authenticated = false;
 }
 }
 else
 {
 // Username/password are not valid...
 e.Authenticated = false;
 }
}

 

 

 Si tratamos de ingresar a la aplicacion suministrando un username y password validos, pero premeditadamente un email address incorrecto, lograremos la siguiente pantalla con un mensaje de credenciales invalidas.

 

Mejorando el Mensaje de Credenciales Invalidas

Cuando un usuario trata de ingresar con credenciales invalidas, el web control Login muestra un mensaje  que el intento fue insatisfactorio, muestra el mensaje que esta definido en la propiedad FailureText, por defecto el mensaje es: “Your login attempt was not successful. Please try again.”

Hay varias maneras por las cuales las credenciales pueden ser invalidas:

  • El username no existe
  • El username existe, pero el password es invalido
  • El username y password son validos pero el usuario no esta aprobado
  • El username y password son validos, pero el usuario esta bloqueado (probablemente excedio el numero maximo de intentos de login en un tiempo determinado)

Cuando la autentificacion es personalizada existen situaciones adicionales para que las cuales las credenciales sean invalidas.

Independientemente de la causa de que las credenciales sean invalidas el web control Login muestra el mismo mensaje y esto puede confundir al usuario, pero este mensaje puede tambien ser personalisado segun la situacion.

Cualquiera que sea la razon por la que las credenciales son invalidas, el web control Login inicia el evento LoginError, por lo que se puede crear un “event handler” para este evento:

protected void myLogin_LoginError(object sender, EventArgs e)
{
 // Determine why the user could not login...
 myLogin.FailureText = "Your login attempt was not successful. Please try again.";

 // Does there exist a User account for this user?
 MembershipUser usrInfo = Membership.GetUser(myLogin.UserName);
 if (usrInfo != null)
 {
 // Is this user locked out?
 if (usrInfo.IsLockedOut)
 {
 myLogin.FailureText = "Your account has been locked out because of too many invalid login attempts. Please contact the administrator to have your account unlocked.";
 }
 else if (!usrInfo.IsApproved)
 {
 myLogin.FailureText = "Your account has not yet been approved. You cannot login until an administrator has approved your account.";
 }
 }
}

 

Este codigo define la propiedad “FailureText” del control Login como: “Your login attempt was not successful. Please try again”. Luego verifica que el username suministrado corresponde a una cuenta existente luego se hace una consulta a las propiedades del objeto MembershipUser:  IsLockedOut and IsApproved para verificar que la cuenta no ha sido bloqueada o no ha sido aprobada. En cada caso, la propiedad FailureText es actualizada a un valor determinado. Si una cuanta ha sido bloqueda y luego se intenta ingrasar uno lograra una pantalla como la siguiente.

 

 

 

Comohemos visto, hasy muchas formas de validar si el usuario es uno con derecho a ingresar a nuestra aplicacion o no. La complejida puede estar determinada por nuestra aplicacion y sus requerimientos, y cuan compleja y segura queremos hacer el proceso de ingresar a la aplicacion, pero aqui tienes la base para (y mas de eso) para casi cualquier grado de complejida que requieras. Provecho!!!! Bon appetite y diviertete programando.

Tags: , ,

Categoría: Manejo de Usuarios en .Net - Membership

Comentarios (20) -

Jose
Jose Peru
26/10/2012 21:50:03 #

muy bueno el tutorial sera de gran ayuda, muchas gracias maestro, tambien puedo quitar algun texbox del control, ejemplo no requiero los campos de pregunta secreta y respuesta, se puede quitar?

Jolie
Jolie
12/06/2013 4:34:39 #

Great Post!!!!

Winfred
Winfred
12/06/2013 22:55:59 #

Hello There. I found your blog using msn. This is a really well written article. I will make sure to bookmark it and return to read more of your useful info. Thanks for the post. I will definitely return.

Here is my web site  Winfred - queopinascolombia.com/.../ * PERMITIDO

Adrian
Adrian
13/06/2013 18:48:09 #

Hello this is kind of of off topic but I was wondering if blogs use WYSIWYG editors or if you have to manually code with HTML. I'm starting a blog soon but have no coding know-how so I wanted to get guidance from someone with experience. Any help would be enormously appreciated!

Mariam
Mariam
14/06/2013 8:08:05 #

It's a pity you don't have a donate button! I'd most certainly donate to this outstanding blog! I suppose for now i'll settle for book-marking and adding your RSS feed to my Google account. I look forward to brand new updates and will talk about this website with my Facebook group. Chat soon!

Dona
Dona
14/06/2013 11:23:55 #

With havin so much written content do you ever run into any issues of plagorism or copyright violation? My blog has a lot of exclusive content I've either created myself or outsourced but it appears a lot of it is popping it up all over the web without my authorization. Do you know any techniques to help reduce content from being stolen? I'd genuinely appreciate it.

My site ::  mp3 player 4 - http://liga-masterov.net/ad/6604

Penelope
Penelope
14/06/2013 12:39:31 #

Thanks very interesting blog!

Carlo
Carlo
15/06/2013 11:27:54 #

Quality articles or reviews is the secret to interest the viewers to go to see the web page, that's what this web site is providing.

Maricruz
Maricruz
15/06/2013 21:26:22 #

Thank you a lot for sharing this with all folks you really know what you're speaking about! Bookmarked. Kindly additionally consult with my site =).  

Francis
Francis
16/06/2013 0:59:32 #

Woah! I'm really enjoying the template/theme of this website. It's simple, yet effective. A lot of times it's challenging to get that "perfect balance" between usability and visual appearance. I must say that you've done a excellent job with this. Also, the blog loads super quick for me on Internet explorer. Superb Blog!http://ivukaarts.com/member/61124/

Maybelle
Maybelle
16/06/2013 12:41:09 #

Good Job dude

Lilliana
Lilliana
16/06/2013 12:42:12 #

Nice theme, I love blog engine

Tracie
Tracie
16/06/2013 12:43:01 #

Thanks a lot for your ideas

Christina
Christina
16/06/2013 14:30:16 #

Thanks

Tammara
Tammara
16/06/2013 16:40:10 #

Wow, this article is good, my younger sister is analyzing these things, therefore I am going to let know her.

Rosella
Rosella
16/06/2013 16:40:25 #

I am sure this piece of writing has touched all the internet visitors, its really really good paragraph on building up new web site.

Nathan
Nathan
16/06/2013 22:00:51 #

Great job

tauHong
tauHong
17/06/2013 8:25:12 #

I am really enjoying the theme/design of your blog. Do you ever run into any browser compatibility problems? A few of my blog audience have complained about my website not operating correctly in Explorer but looks great in Safari. Do you have any tips to help fix this problem?

Maynard
Maynard
17/06/2013 20:48:52 #

hello!,I really like your writing very a lot! proportion we keep up a correspondence more about your post on AOL? I need a specialist in this house to resolve my problem. Maybe that's you! Having a look forward to look you.

Kristi
Kristi
18/06/2013 9:03:30 #

These are in fact enormous ideas in about blogging. You have touched some pleasant factors here. Any way keep up wrinting.

No se aceptan más comentarios

Acerca del Autor

Osmar Ricardo Medina del Perú, consultor en Técnología de Infomación (TI). (más acerca de Osmar) ,  con experiencia en diferentes niveles de responsabilidad en el desarrollo de sistemas y pasión por la tecnología y su impacto en la sociedad.

Lista por Mes

Lista de Páginas