Cómo: Implementar un usuario suscrito personalizado
Actualización: noviembre 2007
Proporciona un ejemplo que muestra cómo extender la clase MembershipUser con un proveedor de suscripciones personalizado.
Aunque el espacio de nombres System.Web.Profile del usuario constituye un mecanismo útil para almacenar la información de cada usuario en una aplicación Web, quizás el diseño de la aplicación requiera que se almacenen datos adicionales junto con la información de autenticación del usuario en el almacén de datos Membership. En este caso, sería necesario generar un proveedor de suscripciones personalizado para almacenar y recuperar la información de autenticación del usuario y otros valores de usuario en el almacén de datos (para obtener un ejemplo de proveedor de suscripciones personalizado, vea Implementar un proveedor de suscripciones). Además, puede extender la clase MembershipUser para que los valores de usuario agregados estén disponibles para el código de aplicación.
Para crear un usuario suscrito personalizado, es necesario realizar las tareas siguientes:
Cree una clase que herede de la clase MembershipUser.
Cree un origen de datos para almacenar la información de autenticación y otra configuración del usuario.
Cree un proveedor de suscripciones personalizado para el almacén de datos. El proveedor de suscripciones personalizado contendrá código adicional que puede recibir como entrada y devolver objetos del tipo de usuario suscrito personalizado.
En los ejemplos de este tema se muestra cómo modificar el ejemplo de proveedor de suscripciones personalizado incluido en Cómo: Ejemplo de implementación del proveedor de suscripciones para admitir una implementación de usuario suscrito personalizado.
Para crear un usuario suscrito personalizado, puede crear una clase que herede de la clase MembershipUser y, a continuación, incluir propiedades que expongan los valores de usuario adicionales. Opcionalmente, también puede agregar métodos y eventos a la clase MembershipUser.
Cuando se llama a la clase Membership para crear una instancia de la clase MembershipUser personalizada, se llama sólo a los constructores definidos por la clase MembershipUser. Si la implementación de MembershipUser incluye sobrecargas de constructor adicionales, se llamará a esos constructores únicamente desde el código de aplicación que se haya escrito específicamente para llamar a un constructor personalizado.
El ejemplo de código siguiente muestra un usuario suscrito personalizado simple que hereda de la clase MembershipUser y proporciona dos propiedades adicionales: IsSubscriber, que es una propiedad booleana que indica si el usuario se suscribe a un servicio o boletín para una aplicación Web, y CustomerID, que contiene un identificador único para una base de datos de cliente independiente.
using System; using System.Web.Security; namespace Samples.AspNet.Membership.CS { public class OdbcMembershipUser : MembershipUser { private bool _IsSubscriber; private string _CustomerID; public bool IsSubscriber { get { return _IsSubscriber; } set { _IsSubscriber = value; } } public string CustomerID { get { return _CustomerID; } set { _CustomerID = value; } } public OdbcMembershipUser(string providername, string username, object providerUserKey, string email, string passwordQuestion, string comment, bool isApproved, bool isLockedOut, DateTime creationDate, DateTime lastLoginDate, DateTime lastActivityDate, DateTime lastPasswordChangedDate, DateTime lastLockedOutDate, bool isSubscriber, string customerID) : base(providername, username, providerUserKey, email, passwordQuestion, comment, isApproved, isLockedOut, creationDate, lastLoginDate, lastActivityDate, lastPasswordChangedDate, lastLockedOutDate) { this.IsSubscriber = isSubscriber; this.CustomerID = customerID; } } }
Para obtener un ejemplo de cómo modificar el control CreateUserWizard para incluir información adicional para un usuario suscrito, vea Cómo: Personalizar el control CreateUserWizard de ASP.NET.
Necesitará proporcionar un almacén de datos donde guardar la información de autenticación de usuario para la característica de suscripción, así como la información de usuario adicional para el usuario suscrito personalizado.
En el ejemplo de código siguiente se muestra una consulta que se puede ejecutar en una base de datos de Microsoft Access para crear una tabla que almacene la información de autenticación y los valores de propiedad para el usuario suscrito personalizado.
CREATE TABLE Users ( PKID Guid NOT NULL PRIMARY KEY, Username Text (255) NOT NULL, ApplicationName Text (255) NOT NULL, Email Text (128) NOT NULL, Comment Text (255), Password Text (128) NOT NULL, PasswordQuestion Text (255), PasswordAnswer Text (255), IsApproved YesNo, LastActivityDate DateTime, LastLoginDate DateTime, LastPasswordChangedDate DateTime, CreationDate DateTime, IsOnLine YesNo, IsLockedOut YesNo, LastLockedOutDate DateTime, FailedPasswordAttemptCount Integer, FailedPasswordAttemptWindowStart DateTime, FailedPasswordAnswerAttemptCount Integer, FailedPasswordAnswerAttemptWindowStart DateTime, IsSubscriber YesNo, CustomerID Text (64) )
Necesitará crear un proveedor de suscripciones personalizado que sea compatible con el tipo de usuario suscrito personalizado y con el almacén de datos de suscripción personalizado. Se pueden escribir los métodos GetUser y CreateUser del proveedor de suscripciones personalizado para devolver objetos del tipo de usuario suscrito personalizado. El método UpdateUser del proveedor de suscripciones personalizado se puede escribir para recibir como entrada un objeto del tipo de usuario suscrito personalizado.
En las secciones siguientes se proporcionan instrucciones para crear un proveedor de suscripciones personalizado que utilice un tipo de usuario suscrito personalizado. Los ejemplos se basan en el código proporcionado en Cómo: Ejemplo de implementación del proveedor de suscripciones y utilizan el esquema de base de datos de la sección Crear un origen de datos para los datos del usuario suscrito expuesta con anterioridad en este tema.
Modificar los métodos GetUser
Al trabajar con un tipo de usuario suscrito personalizado, los métodos MembershipProvider.GetUser y MembershipProvider.GetUser del proveedor de suscripciones todavía deben devolver un objeto del tipo MembershipUser. Partiendo de que la clase de usuario suscrito personalizado hereda de la clase MembershipUser, devuelva un objeto del tipo de usuario suscrito personalizado como el valor devuelto para la implementación de los métodos de GetUser. Después, el código de aplicación puede convertir el objeto MembershipUser devuelto como tipo de usuario suscrito personalizado para tener acceso a los miembros adicionales del usuario suscrito personalizado, como se muestra en el ejemplo de código siguiente.
El ejemplo de código siguiente muestra los métodos modificados de GetUser (y el método privado complementario) del proveedor de suscripciones de ejemplo de Cómo: Ejemplo de implementación del proveedor de suscripciones, que se ha actualizado para devolver el tipo de usuario suscrito personalizado incluido con anterioridad, en la sección Crear un usuario suscrito personalizado de este tema.
// // MembershipProvider.GetUser(string, bool) // public override MembershipUser GetUser(string username, bool userIsOnline) { OdbcConnection conn = new OdbcConnection(connectionString); OdbcCommand cmd = new OdbcCommand("SELECT PKID, Username, Email, PasswordQuestion," + " Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," + " LastActivityDate, LastPasswordChangedDate, LastLockedOutDate," + " IsSubscriber, CustomerID" + " FROM Users WHERE Username = ? AND ApplicationName = ?", conn); cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username; cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName; OdbcMembershipUser u = null; OdbcDataReader reader = null; try { conn.Open(); reader = cmd.ExecuteReader(); if (reader.HasRows) { reader.Read(); u = GetUserFromReader(reader); if (userIsOnline) { OdbcCommand updateCmd = new OdbcCommand("UPDATE Users " + "SET LastActivityDate = ? " + "WHERE Username = ? AND Applicationname = ?", conn); updateCmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = DateTime.Now; updateCmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username; updateCmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName; updateCmd.ExecuteNonQuery(); } } } catch (OdbcException e) { if (WriteExceptionsToEventLog) { WriteToEventLog(e, "GetUser(String, Boolean)"); throw new ProviderException(exceptionMessage); } else { throw e; } } finally { if (reader != null) { reader.Close(); } conn.Close(); } return u; } // // MembershipProvider.GetUser(object, bool) // public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) { OdbcConnection conn = new OdbcConnection(connectionString); OdbcCommand cmd = new OdbcCommand("SELECT PKID, Username, Email, PasswordQuestion," + " Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," + " LastActivityDate, LastPasswordChangedDate, LastLockedOutDate," + " IsSubscriber" + " FROM Users WHERE PKID = ?", conn); cmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey; OdbcMembershipUser u = null; OdbcDataReader reader = null; try { conn.Open(); reader = cmd.ExecuteReader(); if (reader.HasRows) { reader.Read(); u = GetUserFromReader(reader); if (userIsOnline) { OdbcCommand updateCmd = new OdbcCommand("UPDATE Users " + "SET LastActivityDate = ? " + "WHERE PKID = ?", conn); updateCmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = DateTime.Now; updateCmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey; updateCmd.ExecuteNonQuery(); } } } catch (OdbcException e) { if (WriteExceptionsToEventLog) { WriteToEventLog(e, "GetUser(Object, Boolean)"); throw new ProviderException(exceptionMessage); } else { throw e; } } finally { if (reader != null) { reader.Close(); } conn.Close(); } return u; } // // GetUserFromReader // A helper function that takes the current row from the OdbcDataReader // and hydrates a MembershipUser from the values. Called by the // MembershipUser.GetUser implementation. // private OdbcMembershipUser GetUserFromReader(OdbcDataReader reader) { object providerUserKey = reader.GetValue(0); string username = reader.GetString(1); string email = reader.GetString(2); string passwordQuestion = ""; if (reader.GetValue(3) != DBNull.Value) passwordQuestion = reader.GetString(3); string comment = ""; if (reader.GetValue(4) != DBNull.Value) comment = reader.GetString(4); bool isApproved = reader.GetBoolean(5); bool isLockedOut = reader.GetBoolean(6); DateTime creationDate = reader.GetDateTime(7); DateTime lastLoginDate = new DateTime(); if (reader.GetValue(8) != DBNull.Value) lastLoginDate = reader.GetDateTime(8); DateTime lastActivityDate = reader.GetDateTime(9); DateTime lastPasswordChangedDate = reader.GetDateTime(10); DateTime lastLockedOutDate = new DateTime(); if (reader.GetValue(11) != DBNull.Value) lastLockedOutDate = reader.GetDateTime(11); bool isSubscriber = false; if (reader.GetValue(12) != DBNull.Value) isSubscriber = reader.GetBoolean(12); string customerID = String.Empty; if (reader.GetValue(13) != DBNull.Value) customerID = reader.GetString(13); OdbcMembershipUser u = new OdbcMembershipUser(this.Name, username, providerUserKey, email, passwordQuestion, comment, isApproved, isLockedOut, creationDate, lastLoginDate, lastActivityDate, lastPasswordChangedDate, lastLockedOutDate, isSubscriber, customerID); return u; }
Modificar el método UpdateUser
Cuando trabaje con un tipo de usuario suscrito personalizado y un proveedor de suscripciones personalizado, implemente un método UpdateUser que utilice como entrada un objeto del tipo MembershipUser. En su implementación del método UpdateUser, convierta el objeto MembershipUser proporcionado como su tipo de usuario suscrito personalizado para tener acceso a los valores de las propiedades adicionales y actualizarlos en el almacén de datos.
El ejemplo de código siguiente muestra el método modificado UpdateUser del proveedor de suscripciones de ejemplo de Cómo: Ejemplo de implementación del proveedor de suscripciones, que se ha actualizado para convertir el usuario proporcionado como el tipo de usuario suscrito personalizado incluido anteriormente, en la sección Crear un usuario suscrito personalizado de este tema.
public override void UpdateUser(MembershipUser user) { OdbcConnection conn = new OdbcConnection(connectionString); OdbcCommand cmd = new OdbcCommand("UPDATE Users " + " SET Email = ?, Comment = ?," + " IsApproved = ?, IsSubscriber = ?, CustomerID = ?" + " WHERE Username = ? AND ApplicationName = ?", conn); OdbcMembershipUser u = (OdbcMembershipUser)user; cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = user.Email; cmd.Parameters.Add("@Comment", OdbcType.VarChar, 255).Value = user.Comment; cmd.Parameters.Add("@IsApproved", OdbcType.Bit).Value = user.IsApproved; cmd.Parameters.Add("@IsSubscriber", OdbcType.Bit).Value = u.IsSubscriber; cmd.Parameters.Add("@CustomerID", OdbcType.VarChar, 128).Value = u.CustomerID; cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = user.UserName; cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName; try { conn.Open(); cmd.ExecuteNonQuery(); } catch (OdbcException e) { if (WriteExceptionsToEventLog) { WriteToEventLog(e, "UpdateUser"); throw new ProviderException(exceptionMessage); } else { throw e; } } finally { conn.Close(); } }
Modificar el método CreateUser
Al trabajar con un tipo de usuario suscrito personalizado y un proveedor de suscripciones personalizado, el proveedor de suscripciones personalizado debe implementar un método CreateUser que utilice como entrada solamente las propiedades admitidas por la clase MembershipUser. Puede crear una sobrecarga del método CreateUser que utilice valores de propiedad adicionales, como se muestra en el ejemplo de código siguiente.
Sin embargo, ni la clase Membership ni los controles que se basen en la clase Membership, como el control CreateUserWizard, llamarán a esta sobrecarga. Para llamar a este método desde una aplicación, convierta la instancia de MembershipProvider a la que hace referencia la clase Membership como tipo de proveedor de suscripciones personalizado y, a continuación, llame directamente a la sobrecarga de CreateUser.
Si su aplicación utiliza el control CreateUserWizard para agregar nuevos usuarios al origen de datos de suscripción, puede personalizar los pasos del asistente del control CreateUserWizard para incluir controles que recuperen los valores de propiedad adicionales del usuario suscrito personalizado. Después, puede controlar el evento CreatedUser del control CreateUserWizard y agregar código de evento que haga lo siguiente:
-
Recuperar los valores de propiedad del usuario suscrito adicional.
-
Convertir el usuario suscrito creado por el control CreateUserWizard como tipo de usuario suscrito personalizado.
-
Establecer las propiedades adicionales del usuario suscrito.
-
Pasar el usuario actualizado al método UpdateUser de la clase Membership. A continuación se llamará al método UpdateUser del proveedor personalizado (que se ha descrito anteriormente, en la sección Modificar el método UpdateUser de este tema) para agregar valores de propiedad adicionales al origen de datos.
Nota:
|
|---|
|
Para obtener un ejemplo de cómo modificar los pasos de CreateUserWizard, vea Cómo: Personalizar el control CreateUserWizard de ASP.NET. |
El ejemplo de código siguiente muestra el método modificado CreateUser del proveedor de suscripciones de ejemplo de Cómo: Ejemplo de implementación del proveedor de suscripciones, que se ha actualizado para devolver el tipo de usuario suscrito personalizado incluido anteriormente, en la sección Crear un usuario suscrito personalizado de este tema. Se ha creado una sobrecarga para obtener como entrada los valores de las propiedades adicionales del proveedor de suscripciones personalizado.
// // MembershipProvider.CreateUser // public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) { return this.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, false, "", out status); } // // OdbcMembershipProvider.CreateUser -- returns OdbcMembershipUser // public OdbcMembershipUser CreateUser( string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, bool isSubscriber, string customerID, out MembershipCreateStatus status) { ValidatePasswordEventArgs args = new ValidatePasswordEventArgs(username, password, true); OnValidatingPassword(args); if (args.Cancel) { status = MembershipCreateStatus.InvalidPassword; return null; } if (RequiresUniqueEmail && GetUserNameByEmail(email) != "") { status = MembershipCreateStatus.DuplicateEmail; return null; } MembershipUser u = GetUser(username, false); if (u == null) { DateTime createDate = DateTime.Now; if (providerUserKey == null) { providerUserKey = Guid.NewGuid(); } else { if ( !(providerUserKey is Guid) ) { status = MembershipCreateStatus.InvalidProviderUserKey; return null; } } OdbcConnection conn = new OdbcConnection(connectionString); OdbcCommand cmd = new OdbcCommand("INSERT INTO Users " + " (PKID, Username, Password, Email, PasswordQuestion, " + " PasswordAnswer, IsApproved," + " Comment, CreationDate, LastPasswordChangedDate, LastActivityDate," + " ApplicationName, IsLockedOut, LastLockedOutDate," + " FailedPasswordAttemptCount, FailedPasswordAttemptWindowStart, " + " FailedPasswordAnswerAttemptCount, FailedPasswordAnswerAttemptWindowStart, " + " IsSubscriber, CustomerID)" + " Values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", conn); cmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey; cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username; cmd.Parameters.Add("@Password", OdbcType.VarChar, 255).Value = EncodePassword(password); cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = email; cmd.Parameters.Add("@PasswordQuestion", OdbcType.VarChar, 255).Value = passwordQuestion; cmd.Parameters.Add("@PasswordAnswer", OdbcType.VarChar, 255).Value = EncodePassword(passwordAnswer); cmd.Parameters.Add("@IsApproved", OdbcType.Bit).Value = isApproved; cmd.Parameters.Add("@Comment", OdbcType.VarChar, 255).Value = ""; cmd.Parameters.Add("@CreationDate", OdbcType.DateTime).Value = createDate; cmd.Parameters.Add("@LastPasswordChangedDate", OdbcType.DateTime).Value = createDate; cmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = createDate; cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName; cmd.Parameters.Add("@IsLockedOut", OdbcType.Bit).Value = false; cmd.Parameters.Add("@LastLockedOutDate", OdbcType.DateTime).Value = createDate; cmd.Parameters.Add("@FailedPasswordAttemptCount", OdbcType.Int).Value = 0; cmd.Parameters.Add("@FailedPasswordAttemptWindowStart", OdbcType.DateTime).Value = createDate; cmd.Parameters.Add("@FailedPasswordAnswerAttemptCount", OdbcType.Int).Value = 0; cmd.Parameters.Add("@FailedPasswordAnswerAttemptWindowStart", OdbcType.DateTime).Value = createDate; cmd.Parameters.Add("@IsSubscriber", OdbcType.Bit).Value = isSubscriber; cmd.Parameters.Add("@CustomerID", OdbcType.VarChar, 128).Value = customerID; try { conn.Open(); int recAdded = cmd.ExecuteNonQuery(); if (recAdded > 0) { status = MembershipCreateStatus.Success; } else { status = MembershipCreateStatus.UserRejected; } } catch (OdbcException e) { if (WriteExceptionsToEventLog) { WriteToEventLog(e, "CreateUser"); } status = MembershipCreateStatus.ProviderError; } finally { conn.Close(); } return (OdbcMembershipUser)GetUser(username, false); } else { status = MembershipCreateStatus.DuplicateUserName; } return null; }
Nota: