Recuperar y cambiar las contraseñas (VB)

por Scott Mitchell

Nota:

Desde que se escribió este artículo, los proveedores de pertenencia a ASP.NET han sido reemplazados por ASP.NET Identity. Se recomienda encarecidamente actualizar las aplicaciones para usar la plataforma ASP.NET Identity en lugar de los proveedores de pertenencia destacados en el momento en que se escribió este artículo. ASP.NET Identity tiene una serie de ventajas sobre el sistema de pertenencia ASP.NET, incluidas las siguientes:

  • Mejor rendimiento
  • Extensibilidad y capacidad de prueba mejoradas
  • Compatibilidad con OAuth, OpenID Connect y autenticación en dos fases
  • Compatibilidad con identidades basadas en notificaciones
  • Mejor interoperabilidad con ASP.Net Core

ASP.NET incluye dos controles web para ayudar a recuperar y cambiar contraseñas. El control PasswordRecovery permite a un visitante recuperar su contraseña perdida. El control ChangePassword permite al usuario actualizar su contraseña. Al igual que los otros controles web relacionados con el inicio de sesión que hemos visto en esta serie de tutoriales, los controles PasswordRecovery y ChangePassword funcionan con el marco de pertenencia en segundo plano para restablecer o modificar las contraseñas de los usuarios.

Introducción

Entre los sitios web de mi banco, compañía de servicios públicos, compañía telefónica, cuentas de correo electrónico y portales web personalizados, como la mayoría de las personas, tengo que recordar docenas de contraseñas diferentes. Con tantas credenciales que hay que memorizar estos días, no es raro que las personas olviden su contraseña. Para tenerlo en cuenta, los sitios web que ofrecen cuentas de usuario deben incluir una manera de que los usuarios recuperen su contraseña. Este proceso normalmente implica generar una nueva contraseña aleatoria y enviarla por correo electrónico a la dirección de correo electrónico del usuario en el archivo. Después de recibir su nueva contraseña, la mayoría de los usuarios vuelven al sitio web y cambian su contraseña de la generada aleatoriamente a una más fácil de recordar.

ASP.NET incluye dos controles web para ayudar a recuperar y cambiar contraseñas. El control PasswordRecovery permite a un visitante recuperar su contraseña perdida. El control ChangePassword permite al usuario actualizar su contraseña. Al igual que los otros controles web relacionados con el inicio de sesión que hemos visto en esta serie de tutoriales, los controles PasswordRecovery y ChangePassword funcionan con el marco de pertenencia en segundo plano para restablecer o modificar las contraseñas de los usuarios.

En este tutorial examinaremos el uso de estos dos controles. También veremos cómo cambiar y restablecer mediante programación la contraseña de un usuario a través de los métodos y de clase MembershipUser, ChangePassword y ResetPassword.

Paso 1: Ayudar a los usuarios a recuperar contraseñas perdidas

Todos los sitios web que admiten cuentas de usuario deben proporcionar a los usuarios algún mecanismo para recuperar sus contraseñas olvidadas. La buena noticia es que implementar esta funcionalidad en ASP.NET es muy sencillo gracias al control web PasswordRecovery. El control PasswordRecovery representa una interfaz que solicita al usuario su nombre de usuario y, si es necesario, la respuesta a su pregunta de seguridad. A continuación, envía un correo electrónico al usuario con su contraseña.

Nota:

Dado que los mensajes de correo electrónico se transmiten a través de la conexión en texto sin formato, hay riesgos de seguridad implicados en el envío de la contraseña de un usuario por correo electrónico.

El control PasswordRecovery consta de tres vistas:

  • Nombre de usuario: solicita al visitante su nombre de usuario. Esta es la vista inicial.
  • Pregunta: muestra el nombre de usuario y la pregunta de seguridad del usuario como texto, junto con un cuadro de texto para que el usuario escriba la respuesta a su pregunta de seguridad.
  • Correcto: se muestra un mensaje que informa al usuario de que se ha enviado su contraseña por correo electrónico.

Las vistas mostradas y las acciones realizadas por el control PasswordRecovery dependen de las siguientes opciones de configuración de pertenencia:

  • RequiresQuestionAndAnswer
  • EnablePasswordRetrieval
  • EnablePasswordReset

La configuración del RequiresQuestionAndAnswer marco de pertenencia indica si los usuarios deben especificar una pregunta de seguridad y responder al registrarse para una cuenta. Como se describe en el tutorial de Creación de cuentas de usuario, si RequiresQuestionAndAnswer es True (el valor predeterminado), la interfaz de CreateUserWizard incluye controles de cuadro de texto para la pregunta y respuesta del nuevo usuario; si RequiresQuestionAndAnswer es False, no se recopila dicha información. Del mismo modo, si RequiresQuestionAndAnswer es True, el control PasswordRecovery muestra la vista Pregunta después de que el usuario haya escrito su nombre de usuario; la contraseña solo se recupera si el usuario escribe la respuesta de seguridad correcta. Sin embargo, si RequiresQuestionAndAnswer es False, el control PasswordRecovery pasa directamente de la vista UserName a la vista Correcto.

Después de que el usuario haya proporcionado su nombre de usuario (o su nombre de usuario y respuesta de seguridad, si RequiresQuestionAndAnswer es True), PasswordRecovery le envía un correo electrónico con su contraseña al usuario. Si la EnablePasswordRetrieval opción se establece en True, se envía al usuario por correo electrónico su contraseña actual. Si se establece en False y EnablePasswordReset se establece en True, el control PasswordRecovery genera una nueva contraseña aleatoria para el usuario y le envía un correo electrónico con esta nueva contraseña. Si tanto EnablePasswordRetrieval como EnablePasswordReset son False, el control PasswordRecovery produce una excepción.

Nota:

Recuerde que SqlMembershipProvider almacena las contraseñas de los usuarios en uno de los tres formatos: Clear, Hashed (valor predeterminado) o Encrypted. El mecanismo de almacenamiento utilizado depende de las opciones de configuración de pertenencia; la aplicación de demostración usa el formato de contraseña hash. Cuando se usa el formato de contraseña hash, la EnablePasswordRetrieval opción debe establecerse en False porque el sistema no puede determinar la contraseña real del usuario de la versión con hash almacenada en la base de datos.

En la ilustración 1 se muestra cómo la interfaz y el comportamiento de PasswordRecovery están influenciados por la configuración de pertenencia.

The RequiresQuestionAndAnswer, EnablePasswordRetrieval, and EnablePasswordReset Influence the PasswordRecovery control's Appearance and Behavior

Ilustración 1: el RequiresQuestionAndAnswer, EnablePasswordRetrieval y EnablePasswordReset influyen en la apariencia y el comportamiento del control PasswordRecovery (Haga clic para ver la imagen a tamaño completo)

Nota:

En el tutorial Creación del esquema de pertenencia en SQL Server hemos configurado el proveedor de pertenencia estableciendo RequiresQuestionAndAnswer en True, EnablePasswordRetrieval en False y EnablePasswordReset en True.

Uso del control PasswordRecovery

Echemos un vistazo al uso del control PasswordRecovery en una página de ASP.NET. Abra RecoverPassword.aspx y arrastre y coloque un control PasswordRecovery desde el cuadro de herramientas hasta el diseñador; establezca su ID en RecoverPwd. Al igual que los controles Login y CreateUserWizard Web, las vistas del control PasswordRecovery representan una interfaz compuesta enriquecida que incluye etiquetas, cuadros de texto, botones y controles de validación. Puede personalizar la apariencia de las vistas a través de las propiedades de estilo del control o convirtiendo las vistas en plantillas. Lo dejo como un ejercicio para el lector interesado.

Cuando un usuario visite esta página, escribirá su nombre de usuario y hará clic en el botón Enviar. Dado que hemos establecido la RequiresQuestionAndAnswer propiedad en True en nuestras opciones de configuración de pertenencia, el control PasswordRecovery mostrará la vista Pregunta. Una vez que el usuario escriba su respuesta de seguridad correcta y haga clic en Enviar, el control PasswordRecovery actualizará la contraseña del usuario a una generada aleatoriamente y enviará esta contraseña a la dirección de correo electrónico del archivo. ¡Todo esto ha sido posible sin tener que escribir una sola línea de código!

Antes de probar esta página, hay un fragmento final de configuración que debemos atender: necesitamos especificar la configuración de entrega de correo en Web.config. El control PasswordRecovery se basa en esta configuración para enviar el correo electrónico.

La configuración de entrega de correo se especifica a través del <system.net>elemento del<mailSettings>elemento. Use el <smtp> elementopara indicar el método de entrega y la dirección From predeterminada. El marcado siguiente configura las opciones de correo para usar un servidor SMTP de red denominado smtp.example.com en el puerto 25 y con credenciales de nombre de usuario y contraseña de nombre de usuario y contraseña.

Nota:

<system.net> es un elemento secundario del elemento raíz <configuration> y un elemento relacionado de <system.web>. Por lo tanto, no coloque el <system.net> elemento dentro del <system.web> elemento; en su lugar, colóquelo en el mismo nivel.

<configuration>
 ...
 <system.net>
 <mailSettings>
 <smtp deliveryMethod="Network" from="youraddress@example.com">
 <network
 host="smtp.example.com"
 userName="username"
 password="password"
 port="25" />
 </smtp>
 </mailSettings>
 </system.net>
</configuration>

Además de usar un servidor SMTP en la red, también puede especificar un directorio de recogida en el que se deben depositar los mensajes de correo electrónico que se van a enviar.

Una vez que haya configurado las opciones SMTP, visite la RecoverPassword.aspx página a través de un explorador. En primer lugar, intente escribir un nombre de usuario que no exista en el almacén de usuarios. Como se muestra en la ilustración 2, el control PasswordRecovery muestra un mensaje que indica que no se pudo acceder a la información del usuario. El texto del mensaje se puede personalizar a través de la propiedad UserNameFailureText del control.

An Error Message is Displayed if an Invalid Username is Entered

Ilustración 2: se muestra un mensaje de error si se escribe un nombre de usuario no válido (Haga clic para ver la imagen a tamaño completo)

Ahora escriba un nombre de usuario. Use el nombre de usuario de una cuenta en el sistema con una dirección de correo electrónico a la que pueda acceder y cuya respuesta de seguridad conozca. Después de escribir el nombre de usuario y hacer clic en Enviar, el control PasswordRecovery muestra su vista Pregunta. Al igual que con la vista UserName, si escribe una respuesta incorrecta, el control PasswordRecovery muestra un mensaje de error (consulte la ilustración 3). Use la QuestionFailureText propiedad para personalizar este mensaje de error.

An Error Message is Displayed if the User Enters an Invalid Security Answer

Ilustración 3: se muestra un mensaje de error si el usuario escribe una respuesta de seguridad no válida (Haga clic para ver la imagen a tamaño completo)

Por último, escriba la respuesta de seguridad correcta y haga clic en Enviar. En segundo plano, el control PasswordRecovery genera una contraseña aleatoria, la asigna a la cuenta de usuario, envía un correo electrónico que informa al usuario de su nueva contraseña (vea la ilustración 4) y, a continuación, muestra la vista Correcto.

The User is Sent an Email with His New Password

Ilustración 4: el usuario se envía un correo electrónico con su nueva contraseña (Haga clic para ver la imagen a tamaño completo)

Personalización del correo electrónico

El correo electrónico predeterminado enviado por el control PasswordRecovery es bastante aburrido (vea la ilustración 4). El mensaje se envía desde la cuenta especificada en el <smtp> atributo del from elemento con la contraseña del firmante y el cuerpo del texto sin formato:

Vuelva al sitio e inicie sesión con la siguiente información.

Nombre de usuario: username

Contraseña: password

Este mensaje se puede personalizar mediante programación a través de un controlador de eventos para el evento SendingMail del control PasswordRecovery o mediante declaración a través de la propiedad MailDefinition. Vamos a explorar ambas opciones.

El evento SendingMail se desencadena justo antes de enviar el mensaje de correo electrónico y es nuestra última oportunidad de ajustar mediante programación el mensaje de correo electrónico. Cuando se genera este evento, el controlador de eventos pasa un objeto de tipo MailMessageEventArgs, cuya propiedad Message contiene una referencia al correo electrónico a punto de enviarse.

Cree un controlador de eventos para el evento SendingMail y agregue el siguiente código, que agrega mediante programación webmaster@example.com a la lista CC.

Protected Sub RecoverPwd_SendingMail(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.MailMessageEventArgs)Handles RecoverPwd.SendingMail
 e.Message.CC.Add("webmaster@example.com")
End Sub

El mensaje de correo electrónico también se puede configurar a través de medios declarativos. La propiedad MailDefinition de PasswordRecovery es un objeto de tipo MailDefinition. La clase MailDefinition ofrece un host de propiedades relacionadas con el correo electrónico, como From, CC, Priority, Subject, IsBodyHtml, BodyFileName, etc. Para los inicios, establezca la Subject propiedad en algo más descriptivo que el usado de forma predeterminada ( Contraseña ), como “Se ha restablecido la contraseña”...

Para personalizar el cuerpo del mensaje de correo electrónico, es necesario crear un archivo de plantilla de correo electrónico independiente que contenga el contenido del cuerpo. Empiece por crear una nueva carpeta en el sitio web denominado EmailTemplates. A continuación, agregue un nuevo archivo de texto a esta carpeta denominada PasswordRecovery.txt y agregue el siguiente contenido:

Your password has been reset, <%UserName%>!

According to our records, you have requested that your password be reset. Your new
password is: <%Password%>

If you have any questions or trouble logging on please contact a site administrator.

Thank you!

Tenga en cuenta el uso de los marcadores de posición <%UserName%> y <%Password%>. El control PasswordRecovery reemplaza automáticamente estos dos marcadores de posición por el nombre de usuario del usuario y la contraseña recuperada antes de enviar el correo electrónico.

Por último, apunte la propiedad BodyFileName de MailDefinition a la plantilla de correo electrónico que acabamos de crear (~/EmailTemplates/PasswordRecovery.txt).

Después de realizar estos cambios, vuelva a visitar la RecoverPassword.aspx página y escriba su nombre de usuario y respuesta de seguridad. Debe recibir un correo electrónico similar al que aparece en la ilustración 5. Tenga en cuenta que webmaster@example.com se ha copiado y que el asunto y el cuerpo se han actualizado.

The Subject, Body, and CC List Have Been Updated

Ilustración 5: se han actualizado el asunto, el cuerpo y la lista CC (Haga clic para ver la imagen a tamaño completo)

Para enviar un correo electrónico con formato HTML establecido IsBodyHtml a True (el valor predeterminado es False) y actualizar la plantilla de correo electrónico para incluir HTML.

La propiedad MailDefinition no es exclusiva de la clase PasswordRecovery. Como veremos en el paso 2, el control ChangePassword también ofrece una propiedad MailDefinition. Además, el control CreateUserWizard incluye una propiedad de este tipo que puede configurar para enviar automáticamente un mensaje de correo electrónico de bienvenida a los nuevos usuarios.

Nota:

Actualmente no hay vínculos en el panel de navegación izquierdo para llegar a la página RecoverPassword.aspx. Un usuario solo estaría interesado en visitar esta página si no pudo iniciar sesión correctamente en el sitio. Por lo tanto, actualice la Login.aspx página para incluir un vínculo a la RecoverPassword.aspx página.

Restablecer la contraseña de un usuario mediante programación

Al restablecer la contraseña de un usuario, el control PasswordRecovery llama al método ResetPassword del objeto MembershipUser. Este método tiene dos sobrecargas:

  • ResetPassword: restablece la contraseña de un usuario. Use esta sobrecarga si RequiresQuestionAndAnswer es False.
  • ResetPassword(securityAnswer): restablece la contraseña de un usuario solo si la securityAnswer proporcionada es correcta. Use esta sobrecarga si RequiresQuestionAndAnswer es True.

Ambas sobrecargas devuelven la nueva contraseña generada aleatoriamente.

Al igual que con los otros métodos del marco de pertenencia, el ResetPassword método delega al proveedor configurado. El SqlMembershipProvider invoca el procedimiento almacenado aspnet_Membership_ResetPassword, pasando el nombre de usuario del usuario, la nueva contraseña y la respuesta de contraseña proporcionada, entre otros campos. El procedimiento almacenado garantiza que la respuesta de contraseña coincida y, a continuación, actualice la contraseña del usuario.

Un par de notas de implementación de bajo nivel:

  • Un usuario bloqueado no puede restablecer su contraseña. Sin embargo, un usuario no aprobado puede. Analizaremos los estados bloqueados y aprobados con más detalle en el tutorial Desbloqueo y aprobación de cuentas de usuario.
  • Si la respuesta de contraseña es incorrecta, se incrementa el número de intentos de respuesta de contraseña con error del usuario. Si se produce un número especificado de intentos de respuesta de seguridad no válidos dentro de un período de tiempo especificado, el usuario se bloquea.

Palabra sobre cómo se generan las contraseñas aleatorias

Las contraseñas generadas aleatoriamente que se muestran en los mensajes de correo electrónico de las ilustraciones 4 y 5 se crean mediante el método GeneratePassword de la clase Membership. Este método acepta dos parámetros de entrada enteros: length y numberOfNonAlphanumericCharacters y devuelve una cadena de al menos length caracteres con al menos numberOfNonAlphanumericCharacters caracteres no alfanuméricos. Cuando se llama a este método desde las clases de pertenencia o los controles web relacionados con el inicio de sesión, los valores de estos dos parámetros se determinan mediante las propiedades MinRequiredPasswordLength y MinRequiredNonalphanumericCharacters de la configuración de pertenencia, que establecemos en 7 y 1, respectivamente.

El GeneratePassword método usa un generador de números aleatorios criptográficomente seguro para asegurarse de que no hay ningún sesgo en lo que se seleccionan los caracteres aleatorios. Además, GeneratePassword es Public, lo que significa que puede usarlo directamente desde la aplicación de ASP.NET si necesita generar cadenas o contraseñas aleatorias.

Nota:

La SqlMembershipProvider clase siempre genera una contraseña aleatoria de al menos 14 caracteres, por lo que si MinRequiredPasswordLength es menor que 14, se omite su valor.

Paso 2: Cambiar contraseñas

Las contraseñas generadas aleatoriamente son difíciles de recordar. Considere la contraseña que se muestra en la ilustración 4: WWGUZv(f2yM:Bd. Intente memorizarla. Ni que decir tiene que, cuando un usuario recibe una contraseña de este tipo generada aleatoriamente, querrá cambiarla por otra más fácil de recordar.

Use el control ChangePassword para crear una interfaz para que un usuario cambie su contraseña. Al igual que el control PasswordRecovery, el control ChangePassword consta de dos vistas: Cambiar contraseña y Correcto. La vista Cambiar contraseña solicita al usuario sus contraseñas antiguas y nuevas. Al proporcionar la contraseña antigua correcta y una contraseña nueva que cumpla los requisitos mínimos de longitud y caracteres no alfanuméricos, el control ChangePassword actualiza la contraseña del usuario y muestra la vista Correcto.

Nota:

El control ChangePassword modifica la contraseña del usuario invocando el objeto MembershipUsermétodo ChangePassword. El método ChangePassword acepta dos parámetros de entrada String (oldPassword y newPassword) y actualiza la cuenta del usuario con la newPassword, asumiendo que la oldPassword suministrada es correcta.

Abra la página ChangePassword.aspx y agregue un control ChangePassword a la página y asígnele el nombre ChangePwd. En este punto, la vista Diseño debe mostrar la vista Cambiar contraseña (vea la ilustración 6). Al igual que con el control PasswordRecovery, puede alternar entre las vistas a través de la etiqueta inteligente del control. Además, las apariencias de estas vistas se pueden personalizar a través de las propiedades de estilo ordenados o al convertirlos en una plantilla.

Add a ChangePassword Control to the Page

Ilustración 6: agregar un control ChangePassword a la página (Haga clic para ver la imagen a tamaño completo)

El control ChangePassword puede actualizar la contraseña del usuario actualmente conectado o la contraseña de otro usuario especificado. Como se muestra en la ilustración 6, la vista Cambiar contraseña predeterminada representa solo tres controles TextBox: uno para la contraseña antigua y dos para la nueva contraseña. Esta interfaz predeterminada se usa para actualizar la contraseña del usuario que ha iniciado sesión actualmente.

Para usar el control ChangePassword para actualizar la contraseña de otro usuario, establezca la propiedad DisplayUserName del control en True. Al hacerlo, se agrega un cuarto TextBox a la página, que solicita el nombre de usuario del usuario cuya contraseña se va a cambiar.

Establecer DisplayUserName en True es útil si desea permitir que un usuario que cierre sesión cambie su contraseña sin tener que iniciar sesión. Personalmente, creo que no hay nada malo al requerir que un usuario inicie sesión antes de permitirle cambiar su contraseña. Por lo tanto, deje DisplayUserName establecido en False (su valor predeterminado). Sin embargo, al tomar esta decisión, básicamente se impide que los usuarios anónimos lleguen a esta página. Actualice las reglas de autorización de direcciones URL del sitio para denegar a los usuarios anónimos visitar ChangePassword.aspx. Si necesita actualizar la memoria en la sintaxis de la regla de autorización de direcciones URL, consulte el tutorial de autorización basada en usuarios.

Nota:

Puede parecer que la propiedad DisplayUserName es útil para permitir que los administradores cambien las contraseñas de otros usuarios. Sin embargo, incluso cuando DisplayUserName se establece en True, se debe conocer y escribir la contraseña antigua correcta. Hablaremos de técnicas para permitir que los administradores cambien las contraseñas de los usuarios en el paso 3.

Visite la página ChangePassword.aspx a través de un explorador y cambie la contraseña. Tenga en cuenta que se muestra un mensaje de error si escribe una nueva contraseña que no cumple los requisitos de longitud de contraseña y caracteres no alfanuméricos especificados en la configuración de pertenencia (vea la ilustración 7).

An error message is displayed if you enter a new password that fails to meet the password length and non-alphanumeric character requirements.

Ilustración 7: agregar un control ChangePassword a la página (Haga clic para ver la imagen a tamaño completo)

Al escribir la contraseña antigua correcta y una nueva contraseña válida, se cambia la contraseña del usuario que ha iniciado sesión y se muestra la vista Success.

Enviar un correo electrónico de confirmación

De forma predeterminada, el control ChangePassword no envía un mensaje de correo electrónico al usuario cuya contraseña se acaba de actualizar. Si desea enviar un correo electrónico, simplemente configure la propiedad MailDefinition del control. Vamos a configurar el control ChangePassword para que el usuario envíe un correo electrónico con formato HTML que contenga su nueva contraseña.

Empiece por crear un nuevo archivo en la EmailTemplates carpeta denominada ChangePassword.htm. Añada el siguiente marcado:

<html>
 <body>
 <h2>Your Password Has Been Changed!</h2>
 <p>
 This email confirms that your password has been changed.
 </p>
 <p>
 To log on to the site, use the following credentials:
 </p>
 <table>
 <tr>
 <td>
 <b>Username:</b>
 </td>
 <td>
 <%UserName%>
 </td>
 </tr>
 <tr>
 <td>
 <b>Password:</b>
 </td>
 <td>
 <%Password%>
 </td>
 </tr>
 </table>
 <p>
 If you have any questions or encounter any problems logging in,
 please contact a site administrator.
 </p>
 </body>
</html>

A continuación, defina las propiedades BodyFileName, IsBodyHtml y Subject de la propiedad MailDefinition del control ChangePassword como ~/EmailTemplates/ChangePassword.htm, True y Se ha cambiado su contraseña, respectivamente.

Después de realizar estos cambios, vuelva a visitar la página y vuelva a cambiar la contraseña. Esta vez, el control ChangePassword envía un correo electrónico personalizado con formato HTML a la dirección de correo electrónico del usuario en el archivo (véase la ilustración 8).

An Email Message Informs the User That Their Password has Changed

Ilustración 8: un mensaje de correo electrónico informa al usuario de que su contraseña ha cambiado (Haga clic para ver la imagen a tamaño completo)

Paso 3: permitir que los administradores cambien las contraseñas de los usuarios

Una característica común en las aplicaciones que admiten cuentas de usuario es la posibilidad de que un usuario administrativo cambie las contraseñas de otros usuarios. A veces, esta funcionalidad es necesaria porque el sistema carece de la capacidad de que los usuarios cambien sus propias contraseñas. En tal caso, la única manera de que un usuario recupere su contraseña olvidada sería que el administrador les asigne una nueva contraseña. Sin embargo, con los controles PasswordRecovery y ChangePassword, los usuarios administrativos no necesitan estar ocupados con el cambio de contraseñas de los usuarios, ya que los usuarios pueden hacerlo por sí mismos.

¿Pero qué ocurre si el cliente insiste en que los usuarios administrativos deben poder cambiar las contraseñas de otros usuarios? Desafortunadamente, agregar esta funcionalidad puede ser un poco de trabajo. Para cambiar la contraseña de un usuario, se debe proporcionar la contraseña antigua y nueva al método ChangePassword del objeto MembershipUser, pero un administrador no debe tener que conocer la contraseña de un usuario para modificarla.

Una solución alternativa consiste en restablecer primero la contraseña del usuario y, a continuación, cambiarla a la nueva contraseña mediante código como el siguiente:

Dim usr As MembershipUser = Membership.GetUser(username)
Dim resetPwd As String = usr.ResetPassword()
usr.ChangePassword(resetPwd, newPassword)

Este código comienza recuperando información sobre el nombre de usuario, que es el usuario cuya contraseña desea cambiar el administrador. A continuación, se invoca el método ResetPassword, que asigna y al usuario una nueva contraseña aleatoria. El método devuelve esta contraseña generada aleatoriamente y se almacena en la variable resetPwd. Ahora que conocemos la contraseña del usuario, podemos cambiarla a través de una llamada a ChangePassword.

El problema es que este código solo funciona si se establece la configuración del sistema de pertenencia de forma que RequiresQuestionAndAnswer sea False. Si RequiresQuestionAndAnswer es True, como sucede con nuestra aplicación, el método ResetPassword debe pasarse la respuesta de seguridad; de lo contrario, producirá una excepción.

Si el marco de pertenencia está configurado para requerir una pregunta y respuesta de seguridad y, sin embargo, el cliente insiste en que los administradores puedan cambiar las contraseñas de los usuarios, tiene tres opciones:

  • Lanza tus manos al aire y dile al cliente que esto es sólo una cosa que no se puede hacer.
  • Establezca RequiresQuestionAndAnswer en False. Esto da como resultado una aplicación menos segura. Imagine que un usuario malintencionado ha obtenido acceso a la bandeja de entrada de correo electrónico de otro usuario. Quizás el usuario comprometido ha dejado su escritorio para ir a comer y no bloqueó su estación de trabajo, o quizás accedió a su correo electrónico desde un terminal público y no cerraron la sesión. En cualquier caso, el usuario malintencionado puede visitar la página de RecoverPassword.aspx y escribir el nombre de usuario del compañero. A continuación, el sistema enviará por correo electrónico la contraseña recuperada sin solicitar la respuesta de seguridad.
  • Omita la capa de abstracción creada por el marco de pertenencia y trabaje directamente con la base de datos de SQL Server. El esquema de pertenencia incluye un procedimiento almacenado denominado aspnet_Membership_SetPassword que establece la contraseña de un usuario y no requiere la respuesta de seguridad ni la contraseña antigua para realizar su tarea.

Ninguna de estas opciones es especialmente atractiva, pero así es como la vida de un desarrollador va a veces.

Seguí adelante e implementé el tercer enfoque, escribiendo código que omite las clasesMembership y MembershipUser y opera directamente contra la base de datos SecurityTutorials.

Nota:

Al trabajar directamente con la base de datos, la encapsulación proporcionada por el marco de pertenencia se rompe. Esta decisión nos vincula al SqlMembershipProvider, haciendo que nuestro código sea menos portable. Además, es posible que este código no funcione según lo previsto en versiones futuras de ASP.NET si cambia el esquema de pertenencia. Este enfoque es una solución alternativa y, como la mayoría de las soluciones alternativas, no es un ejemplo de procedimientos recomendados.

El código tiene algunos bits inactivos y es bastante largo. Por ello, no quiero saturar este tutorial con un examen detallado sobre él. Si está interesado en obtener más información, descargue el código de este tutorial y visite la página ~/Administration/ManageUsers.aspx. En esta página, que creamos en el tutorial anterior, se muestra cada usuario. He actualizado GridView para incluir un vínculo a la página UserInformation.aspx, pasando el nombre de usuario del usuario seleccionado a través de la cadena de consulta. La página UserInformation.aspx muestra información sobre el usuario seleccionado y TextBoxes para cambiar su contraseña (véase la ilustración 9).

Después de escribir la nueva contraseña, confirmarla en el segundo TextBox y hacer clic en el botón Actualizar usuario, se produce una devolución de entrada y se invoca el procedimiento almacenado aspnet_Membership_SetPassword, actualizando la contraseña del usuario. Animo a los lectores interesados en esta funcionalidad a familiarizarse con el código y tratar de ampliar la funcionalidad para incluir el envío de un correo electrónico al usuario cuya contraseña se cambió.

An Administrator May Change a User's Password

Ilustración 9: un administrador puede cambiar la contraseña de un usuario (Haga clic para ver la imagen a tamaño completo)

Nota:

La página UserInformation.aspx solo funciona actualmente si el marco de pertenencia está configurado para almacenar contraseñas en formato Clear o Hashed. Carece del código para cifrar la nueva contraseña, aunque se le invita a agregar esta funcionalidad. La forma en que recomiendo agregar el código necesario es usar un descompilador como Reflector para examinar el código fuente de los métodos de .NET Framework; para empezar, examine el método ChangePassword de la clase SqlMembershipProvider . Esta es la técnica que he usado para escribir el código para crear un hash de la contraseña.

Resumen

ASP.NET ofrece dos controles para ayudar a los usuarios a administrar su contraseña. El control PasswordRecovery es útil para aquellos que han olvidado sus contraseñas. En función de la configuración del marco de pertenencia, el usuario se envía por correo electrónico a su contraseña existente o a una nueva contraseña generada aleatoriamente. El control ChangePassword permite a un usuario actualizar su contraseña.

Al igual que los controles Login y CreateUserWizard, los controles PasswordRecovery y ChangePassword representan una interfaz de usuario enriquecida sin tener que escribir una cola de marcado declarativo o línea de código. Si la interfaz de usuario predeterminada no satisface sus necesidades, puede personalizarla a través de una variedad de propiedades de estilo. Como alternativa, las interfaces de los controles se pueden convertir en plantillas, para un grado de control más fino. En segundo plano, estos controles usan la API de pertenencia, invocando los métodos ResetPassword y ChangePassword del objeto MembershipUser.

¡Feliz programación!

Lecturas adicionales

Para obtener más información sobre los temas tratados en este tutorial, consulte los siguientes recursos:

Acerca del autor

Scott Mitchell, autor de varios libros de ASP/ASP.NET y fundador de 4GuysFromRolla.com, ha estado trabajando con tecnologías web de Microsoft desde 1998. Scott trabaja como consultor independiente, entrenador y escritor. Su último libro es Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Se puede contactar con Scott en mitchell@4guysfromrolla.com o a través de su blog en http://ScottOnWriting.NET.

Agradecimientos especiales a

Esta serie de tutoriales fue revisada por muchos revisores que fueron de gran ayuda. Los revisores principales de este tutorial son Michael Emmings y Suchi Banerjee. ¿Le interesaría revisar mis próximos artículos de MSDN? Si es así, escríbame a mitchell@4GuysFromRolla.com