Implementar un proveedor de suscripciones

Actualización: noviembre 2007

La suscripción de ASP.NET se ha diseñado para que se pueda utilizar con facilidad una serie de proveedores de suscripciones diferentes en las aplicaciones ASP.NET. Puede utilizar los proveedores de suscripciones proporcionados que se incluyen en .NET Framework o puede implementar sus propios proveedores.

Existen dos razones fundamentales para crear un proveedor de suscripciones personalizado:

  • Necesita almacenar la información de suscripción en un origen de datos que no es compatible con los proveedores de suscripciones incluidos en .NET Framework, como una base de datos de FoxPro, una base de datos de Oracle u otros orígenes de datos.

  • Necesita administrar la información de suscripción mediante un esquema de base de datos que es diferente del que utilizan los proveedores que se distribuyen con .NET Framework. Un ejemplo común serían los datos de suscripción que ya existen en una base de datos de SQL Server de una compañía o un sitio Web.

Clases requeridas

Para implementar un proveedor de suscripciones, cree una clase que herede la clase abstracta MembershipProvider del espacio de nombres System.Web.Security. La clase abstracta MembershipProvider hereda la clase abstracta ProviderBase del espacio de nombres System.Configuration.Provider, por lo que debe implementar también los miembros necesarios de la clase ProviderBase. En las tablas siguientes se muestran las propiedades y los métodos necesarios de las clases abstractas ProviderBase y MembershipProvider que debe implementar, junto con una descripción. Para ver una implementación de cada uno de los miembros, vea el código proporcionado en Ejemplo de implementación del proveedor de suscripciones.

Miembros de ProviderBase necesarios

Miembro

Descripción

Método Initialize

Toma como entrada el nombre del proveedor y una colección NameValueCollection de los valores de configuración. Se utiliza para establecer los valores de las propiedades en la instancia del proveedor, entre los que se incluyen los valores específicos de la implementación y las opciones especificadas en el archivo de configuración (Machine.config o Web.config) proporcionado en la configuración.

Miembros de MembershipProvider necesarios

Miembro

Descripción

Propiedad EnablePasswordReset

Valor Boolean especificado en el archivo de configuración (Web.config).

La propiedad EnablePasswordReset indica si los usuarios pueden utilizar el método ResetPassword para sustituir su contraseña actual por una nueva generada aleatoriamente.

Esta propiedad es de sólo lectura.

Propiedad EnablePasswordRetrieval

Valor Boolean especificado en el archivo de configuración (Web.config).

La propiedad EnablePasswordRetrieval indica si los usuarios pueden recuperar su contraseña mediante el método GetPassword.

Esta propiedad es de sólo lectura.

Propiedad RequiresQuestionAndAnswer

Valor Boolean especificado en el archivo de configuración (Web.config).

La propiedad RequiresQuestionAndAnswer indica si los usuarios deben proporcionar una respuesta de contraseña para recuperar su contraseña mediante el método GetPassword o para restablecer su contraseña mediante el método ResetPassword.

Esta propiedad es de sólo lectura.

Propiedad RequiresUniqueEmail

Valor Boolean especificado en el archivo de configuración (Web.config).

La propiedad RequiresUniqueEmail indica si los usuarios deben proporcionar un valor exclusivo de dirección de correo electrónico al crear un usuario. Si en el origen de datos ya existe un usuario para la propiedad ApplicationName actual, el método CreateUser devuelve null (Nothing en Visual Basic) y un valor de estado DuplicateEmail.

Esta propiedad es de sólo lectura.

Propiedad PasswordFormat

Valor MembershipPasswordFormat especificado en el archivo de configuración (Web.config).

La propiedad PasswordFormat indica el formato en que se almacenan las contraseñas. Las contraseñas se pueden almacenar en los formatos Clear, Encrypted y Hashed. Las contraseñas Clear se almacenan en texto sin formato, lo que mejora el rendimiento del almacenamiento y de la recuperación, aunque es menos seguro, puesto que las contraseñas se pueden leer fácilmente si el origen de datos se va comprometido. Las contraseñas Encrypted se cifran cuando se almacenan, y se pueden descifrar durante la comparación o la recuperación de contraseñas. Esto requiere un procesamiento adicional para el almacenamiento y la recuperación de contraseñas, pero es más seguro, ya que las contraseñas no pueden determinarse con facilidad si el origen de datos se ve comprometido. Las contraseñas Hashed se fragmentan utilizando un algoritmo hash unidireccional y un valor salt que se genera aleatoriamente cuando se almacena en la base de datos. Cuando se valida una contraseña, se fragmenta con el valor salt en la base de datos para su comprobación. Las contraseñas fragmentadas no se pueden recuperar.

Puede utilizar el método EncryptPassword y los métodos virtuales DecryptPassword de la clase MembershipProvider para cifrar y descifrar los valores de la contraseña, o puede proporcionar su propio código de cifrado. Si utiliza el método EncryptPassword y los métodos virtuales DecryptPassword de la clase MembershipProvider, las contraseñas Encrypted se cifran utilizando la información clave proporcionada en el elemento Elemento machineKey (Esquema de configuración de ASP.NET) de su configuración.

Esta propiedad es de sólo lectura.

Propiedad MaxInvalidPasswordAttempts

Valor Integer especificado en el archivo de configuración (Web.config).

La propiedad MaxInvalidPasswordAttempts actúa junto con la propiedad PasswordAttemptWindow como medida de protección si un origen no deseado intenta adivinar varias veces la contraseña o la respuesta de contraseña de un usuario suscrito. Si el número de contraseñas o de preguntas de contraseña incorrectas proporcionado por un usuario suscrito supera el valor MaxInvalidPasswordAttempts durante el período de minutos identificado por la propiedad PasswordAttemptWindow, el usuario suscrito se bloquea estableciendo la propiedad IsLockedOut en true hasta que este bloqueo se libera mediante el método UnlockUser. Si se proporciona una contraseña o una respuesta de contraseña válida antes de que se alcance el valor MaxInvalidPasswordAttempts, el contador que realiza el seguimiento del número de intentos no válidos se restablece en cero.

Si la propiedad RequiresQuestionAndAnswer se establece en false, no se realiza un seguimiento de los intentos de respuesta de contraseña incorrectos.

Los intentos incorrectos de contraseña o de respuesta de contraseña se siguen en los métodos ValidateUser, ChangePassword, ChangePasswordQuestionAndAnswer, GetPassword y ResetPassword.

Esta propiedad es de sólo lectura.

Propiedad PasswordAttemptWindow

Valor Integer especificado en el archivo de configuración (Web.config).

Para consultar una descripción, vea la descripción de la propiedad MaxInvalidPasswordAttempts.

Esta propiedad es de sólo lectura.

Propiedad ApplicationName

Nombre de la aplicación que utiliza la información de suscripción especificada en el archivo de configuración (Web.config). La propiedad ApplicationName se almacena en el origen de datos con la información del usuario relacionada y se utiliza cuando se consulta dicha información. Consulte la sección de la propiedad ApplicationName que aparece más adelante en este mismo tema para obtener más información.

Esta propiedad es de lectura y escritura, y tiene como valor predefinido ApplicationPath si no se ha especificado ningún otro valor explícitamente.

CreateUser (método)

Toma como entrada el nombre de un nuevo usuario, una contraseña y una dirección de correo electrónico e inserta un nuevo usuario de la aplicación en el origen de datos. El método CreateUser devuelve un objeto MembershipUser que se rellena con la información del usuario que se acaba de crear. El método CreateUser también define un parámetro out (en Visual Basic, puede utilizar ByRef) que devuelve un valor de MembershipCreateStatus que indica si el usuario se ha creado correctamente o especifica la razón por la que no se ha podido crear correctamente.

El método CreateUser provoca el evento ValidatingPassword, si se ha especificado un MembershipValidatePasswordEventHandler, y continúa o cancela la acción de creación de usuario en función de los resultados del evento. Puede utilizar el método virtual OnValidatingPassword para ejecutar el MembershipValidatePasswordEventHandler especificado.

Método UpdateUser

Toma como entrada un objeto MembershipUser que se ha rellenado con la información del usuario y actualiza el origen de datos con los valores proporcionados.

Método DeleteUser

Toma como entrada el nombre de un usuario y elimina la información de ese usuario del origen de datos. El método DeleteUser devuelve true si el usuario se ha eliminado correctamente; de lo contrario, devuelve false. Se incluye un parámetro Boolean adicional para indicar si la información relacionada con el usuario, como una función o la información del perfil, también se elimina.

Método ValidateUser

Toma como entrada un nombre de usuario y una contraseña y comprueba que los valores coinciden con los del origen de datos. El método ValidateUser devuelve true si el nombre de usuario y la contraseña coinciden; de lo contrario, devuelve false.

Método GetUser

Toma como entrada un identificador de usuario exclusivo y un valor Boolean que especifican si debe actualizarse el valor de LastActivityDate del usuario para indicar que el usuario está conectado en la actualidad. El método GetUser devuelve un objeto MembershipUser que se rellena con los valores actuales del origen de datos del usuario especificado. Si el nombre de usuario no se encuentra en el origen de datos, el método GetUser devuelve null (Nothing en Visual Basic).

Método GetUser

Toma como entrada un nombre de usuario y un valor Boolean que especifican si debe actualizarse el valor de LastActivityDate del usuario para indicar que el usuario está conectado en la actualidad. El método GetUser devuelve un objeto MembershipUser que se rellena con los valores actuales del origen de datos del usuario especificado. Si el nombre de usuario no se encuentra en el origen de datos, el método GetUser devuelve null (Nothing en Visual Basic).

Método GetAllUsers

Devuelve una clase MembershipUserCollection que se rellena con los objetos MembershipUser de todos los usuarios del origen de datos.

Los resultados devueltos por el método GetAllUsers están restringidos por los parámetros pageIndex y pageSize. El parámetro pageSize identifica el número máximo de objetos MembershipUser que se van devolver en la clase MembershipUserCollection. El parámetro pageIndex identifica qué pagina de resultados se va a devolver, donde 1 representa la primera página. El parámetro totalRecords es un parámetro out que se establece en el número total de usuarios suscritos. Por ejemplo, si hubiera 13 usuarios en la base de datos de la aplicación, y el valor de pageIndex fuera 2 y el de pageSize fuera 5, la clase MembershipUserCollection devuelta contendría el intervalo comprendido entre el sexto y el décimo usuario. El parámetro totalRecords se establecería en 13.

Método GetNumberOfUsersOnline

Devuelve un valor entero que es el recuento de todos los usuarios del origen de datos, donde el valor LastActivityDate es posterior a la fecha y hora actuales menos la propiedad UserIsOnlineTimeWindow. La propiedad UserIsOnlineTimeWindow es un valor entero que especifica el número de minutos que se utilizan cuando se determina si un usuario está conectado.

Método ResetPassword

Toma como entrada un nombre de usuario y una respuesta de contraseña, y genera una nueva contraseña aleatoria para el usuario especificado. El método ResetPassword actualiza la información del usuario en el origen de datos con el nuevo valor de la contraseña y devuelve la nueva contraseña como un objeto string. Un mecanismo apropiado para generar una contraseña aleatoria es el método GeneratePassword de la clase Membership.

El método ResetPassword comprueba que la propiedad EnablePasswordReset está establecida en true antes de realizar cualquier acción. Si la propiedad EnablePasswordReset es false, se produce una excepción NotSupportedException. El método ResetPassword comprueba también el valor de la propiedad RequiresQuestionAndAnswer. Si la propiedad RequiresQuestionAndAnswer es true, el método ResetPassword compara el valor del parámetro de respuesta proporcionado con la respuesta de contraseña almacenada en el origen de datos. Si no coinciden, se produce una excepción MembershipPasswordException.

El método ResetPassword provoca el evento ValidatingPassword, si se ha especificado un MembershipValidatePasswordEventHandler, para validar la contraseña que se acaba de generar y continúa o cancela la acción de restablecimiento de contraseña en función de los resultados del evento. Puede utilizar el método virtual OnValidatingPassword para ejecutar el MembershipValidatePasswordEventHandler especificado.

Método GetPassword

Toma como entrada un nombre de usuario y una respuesta de contraseña; a continuación, recupera la contraseña de ese usuario del origen de datos y devuelve esta contraseña como un objeto string.

El método GetPassword comprueba que la propiedad EnablePasswordRetrieval está establecida en true antes de realizar cualquier acción. Si la propiedad EnablePasswordRetrieval es false, se produce una excepción ProviderException.

El método GetPassword comprueba también el valor de la propiedad RequiresQuestionAndAnswer. Si el valor de RequiresQuestionAndAnswer es true, el método GetPassword compara el valor del parámetro de respuesta proporcionado con la respuesta de contraseña almacenada en el origen de datos. Si no coinciden, se produce una excepción MembershipPasswordException.

Método GetUserNameByEmail

Toma como entrada una dirección de correo electrónico y devuelve el primer nombre de usuario del origen de datos cuya dirección de correo electrónico coincide con el valor del parámetro email proporcionado.

Si no se encuentra ningún nombre de usuario con una dirección de correo electrónico que coincida, se devuelve una cadena vacía.

Si se encuentran varios nombres de usuario que coinciden con una dirección de correo electrónico, sólo se devuelve el primer nombre de usuario encontrado.

Método ChangePassword

Toma como entrada un nombre de usuario, la contraseña actual y una nueva contraseña, y actualiza la contraseña en el origen de datos si el nombre de usuario proporcionado y la contraseña actual son válidas. El método ChangePassword devuelve true si el usuario se ha actualizado correctamente; de lo contrario, devuelve false.

El método ChangePassword provoca el evento ValidatingPassword, si se ha especificado un MembershipValidatePasswordEventHandler, y continúa o cancela la acción de cambio de contraseña en función de los resultados del evento. Puede utilizar el método virtual OnValidatingPassword para ejecutar el MembershipValidatePasswordEventHandler especificado.

Método ChangePasswordQuestionAndAnswer

Toma como entrada un nombre de usuario, una contraseña, una pregunta de contraseña y una respuesta de contraseña, y actualiza la pregunta y la respuesta de contraseña en el origen de datos si el nombre de usuario y la contraseña proporcionados son válidos. El método ChangePasswordQuestionAndAnswer devuelve true si se actualizan correctamente la pregunta y la respuesta de contraseña; en caso contrario, devuelve false.

Si el nombre de usuario y la contraseña proporcionados no son válidos, se devuelve false.

Método FindUsersByName

Devuelve una lista de usuarios suscritos donde el nombre de usuario coincide con el parámetro usernameToMatch proporcionado para la propiedad ApplicationName configurada. Por ejemplo, si el parámetro usernameToMatch se establece en "usuario", se devuelve "user1", "user2," "user3," etc. La compatibilidad del carácter comodín depende del origen de datos. Los usuarios se devuelven en orden alfabético por el nombre de usuario.

Los resultados devueltos por el método FindUsersByName están restringidos por los parámetros pageIndex y pageSize. El parámetro pageSize identifica el número de objetos MembershipUser que se van devolver en la clase MembershipUserCollection. El parámetro pageIndex identifica qué pagina de resultados se va a devolver, donde 1 representa la primera página. El parámetro totalRecords es un parámetro out que se establece en el número total de usuarios suscritos que coinciden con el valor de usernameToMatch. Por ejemplo, si se encontraran 13 usuarios en los que el parámetro usernameToMatch coincidiera en parte o completamente con el nombre de usuario y el valor del parámetro pageIndex fuera 2 y el valor del parámetro pageSize fuera 5, la clase MembershipUserCollection contendría el intervalo comprendido entre el sexto y el décimo usuario devuelto. El parámetro totalRecords se establecería en 13.

Método FindUsersByEmail

Devuelve una lista de usuarios suscritos donde el nombre de usuario coincide con el parámetro emailToMatch proporcionado para la propiedad ApplicationName configurada. Por ejemplo, si el parámetro emailToMatch se establece en "address@example.com", se devolverían los usuarios con las direcciones de correo electrónico "address1@example .com", "address2@example .com", etc. La compatibilidad del carácter comodín depende del origen de datos. Los usuarios se devuelven en orden alfabético por el nombre de usuario.

Los resultados devueltos por el método FindUsersByEmail están restringidos por los parámetros pageIndex y pageSize. El parámetro pageSize identifica el número de objetos MembershipUser que se van devolver en la colección MembershipUserCollection. El parámetro pageIndex identifica qué pagina de resultados se va a devolver, donde 1 representa la primera página. El parámetro totalRecords es un parámetro out que se establece en el número total de usuarios suscritos que coinciden con el valor de emailToMatch. Por ejemplo, si se encontraran 13 usuarios en los que el parámetro emailToMatch coincidiera en parte o completamente con el nombre de usuario y el valor del parámetro pageIndex fuera 2 y el valor del parámetro pageSize fuera 5, la clase MembershipUserCollection contendría el intervalo comprendido entre el sexto y el décimo usuario devuelto. El parámetro totalRecords se establecería en 13.

Método UnlockUser

Toma como entrada un nombre de usuario y actualiza el campo en el origen de datos que almacena la propiedad IsLockedOut a false. El método UnlockUser devuelve true si se actualiza correctamente el registro del usuario suscrito; de lo contrario, devuelve false.

ApplicationName

Los proveedores de suscripciones almacenan únicamente la información del usuario de cada aplicación. De este modo, varias aplicaciones ASP.NET pueden utilizar el mismo origen de datos sin que se produzcan conflictos si se utilizan nombres de usuario creados. O bien, varias aplicaciones ASP.NET pueden utilizar el mismo origen de datos de usuario si especifican el mismo valor para la propiedad ApplicationName.

Como los proveedores de suscripciones almacenan por separado la información de usuario de cada aplicación, deberá comprobar que el esquema de datos incluye el nombre de la aplicación, y que éste también se incluye en las consultas y las actualizaciones. Por ejemplo, el comando siguiente se utiliza para recuperar un nombre de usuario de una base de datos, en función de la dirección de correo electrónico, y comprueba que la propiedad ApplicationName está incluida en la consulta.

SELECT Username FROM MyUserTable 
  WHERE Email = 'someone@example.com' AND ApplicationName = 'MyApplication'

Miembros personalizados

Quizás necesite ampliar las interfaces de los proveedores de suscripciones con funciones adicionales que no proporcionan las clases abstractas ProviderBase y MembershipProvider. Podrá obtener acceso a cualquier miembro público que agregue al proveedor de suscripciones utilizando las propiedades Provider o Providers de la clase Membership.

Un ejemplo podría ser un método LockUser que establece la propiedad IsLockedOut en true. En el ejemplo siguiente se muestra cómo se convierte la propiedad Provider, que muestra el proveedor de suscripciones predeterminado de una aplicación, en un tipo de proveedor personalizado para llamar al método personalizado LockUser.

Dim p As MyCustomProvider = CType(Membership.Provider, MyCustomProvider)
p.LockUser(username)
MyCustomProvider p = (MyCustomProvider)Membership.Provider;
p.LockUser(username);

Seguridad para subprocesos

Para cada proveedor de suscripciones especificado en la configuración de una aplicación, ASP.NET crea una única instancia del proveedor de suscripciones que se utiliza para todas las solicitudes de las que se ocupa un objeto HttpApplication. Por tanto, puede tener varias solicitudes ejecutándose simultáneamente. ASP.NET no garantiza la seguridad para subprocesos de las llamadas a su proveedor. Deberá escribir el código del proveedor para que sea seguro para subprocesos. Por ejemplo, si crea una conexión a una base de datos o abre un archivo para su edición, debe hacerlo dentro del miembro al que se ha llamado, como el método CreateUser, en lugar de abrir un archivo o una conexión a la base de datos cuando se llama al método Initialize.

Vea también

Conceptos

Ejemplo de implementación del proveedor de suscripciones

Proteger la exploración del sitio de ASP.NET

Referencia

ValidatePasswordEventArgs

OnValidatingPassword

Otros recursos

Administrar usuarios mediante suscripciones

Proteger sitios web ASP.NET