Asignar roles a los usuarios (C#)
por Scott Mitchell
Nota:
Desde que se escribió este artículo, los proveedores de pertenencia de 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 el que se escribió este artículo. ASP.NET Identity ofrece una serie de ventajas frente al sistema de pertenencia de ASP.NET, incluidas las siguientes:
- Mejor rendimiento
- Extensibilidad y capacidad de prueba mejoradas
- Compatibilidad con OAuth, OpenID Connect y autenticación en dos fases
- Admite identidades basadas en notificaciones
- Mejor interoperabilidad con ASP.Net Core
Descargar código o Descargar PDF
En este tutorial crearemos dos páginas de ASP.NET para ayudar a administrar qué usuarios pertenecen a los roles. La primera página incluirá instalaciones para ver a qué usuarios pertenecen a un rol determinado, a qué roles pertenece un usuario determinado y a la capacidad de asignar o quitar un usuario determinado de un rol determinado. En la segunda página, aumentaremos el control CreateUserWizard para que incluya un paso para especificar a qué roles pertenece el usuario recién creado. Esto resulta útil en escenarios en los que un administrador puede crear nuevas cuentas de usuario.
Introducción
En el tutorial anterior se examinaron el marco roles y SqlRoleProvider
; vimos cómo usar la Roles
clase para crear, recuperar y eliminar roles. Además de crear y eliminar roles, es necesario poder asignar o quitar usuarios de un rol. Desafortunadamente, ASP.NET no se envía con ningún control web para administrar qué usuarios pertenecen a qué roles. En su lugar, debemos crear nuestras propias páginas de ASP.NET para administrar estas asociaciones. La buena noticia es que agregar y quitar usuarios a roles es bastante fácil. La Roles
clase contiene varios métodos para agregar uno o varios usuarios a uno o varios roles.
En este tutorial crearemos dos páginas de ASP.NET para ayudar a administrar qué usuarios pertenecen a los roles. La primera página incluirá instalaciones para ver a qué usuarios pertenecen a un rol determinado, a qué roles pertenece un usuario determinado y a la capacidad de asignar o quitar un usuario determinado de un rol determinado. En la segunda página, aumentaremos el control CreateUserWizard para que incluya un paso para especificar a qué roles pertenece el usuario recién creado. Esto resulta útil en escenarios en los que un administrador puede crear nuevas cuentas de usuario.
Comencemos.
Enumerar qué usuarios pertenecen a los roles
El primer orden de negocio para este tutorial es crear una página web desde la que se pueden asignar roles a los usuarios. Antes de preocuparnos por cómo asignar usuarios a roles, primero nos centraremos en cómo determinar qué usuarios pertenecen a qué roles. Hay dos maneras de mostrar esta información: "por rol" o "por usuario". Podríamos permitir que el visitante seleccione un rol y, a continuación, mostrar todos los usuarios que pertenecen al rol (la pantalla "por rol"), o podríamos pedir al visitante que seleccione un usuario y, a continuación, mostrar los roles asignados a ese usuario (la pantalla "por usuario").
La vista "por rol" es útil en circunstancias en las que el visitante quiere conocer el conjunto de usuarios que pertenecen a un rol determinado; la vista "por usuario" es ideal cuando el visitante necesita conocer los roles de un usuario determinado. Vamos a hacer que nuestra página incluya interfaces "por rol" y "por usuario".
Comenzaremos con la creación de la interfaz "por usuario". Esta interfaz constará de una lista desplegable y una lista de casillas. La lista desplegable se rellenará con el conjunto de usuarios del sistema; las casillas enumerarán los roles. Al seleccionar un usuario en la lista desplegable, se comprobarán los roles a los que pertenece el usuario. La persona que visita la página puede activar o desactivar las casillas para agregar o quitar el usuario seleccionado de los roles correspondientes.
Nota:
El uso de una lista desplegable para enumerar las cuentas de usuario no es una opción ideal para sitios web donde puede haber cientos de cuentas de usuario. Una lista desplegable está diseñada para permitir que un usuario elija un elemento de una lista relativamente corta de opciones. Rápidamente se vuelve inconfundible a medida que crece el número de elementos de lista. Si va a crear un sitio web que tenga un número potencialmente elevado de cuentas de usuario, es posible que desee considerar el uso de una interfaz de usuario alternativa, como una GridView paginable o una interfaz filtrable que muestra al visitante que elija una carta y, a continuación, solo muestra a los usuarios cuyo nombre de usuario comienza con la letra seleccionada.
Paso 1: Compilar la interfaz de usuario "Por usuario"
Abra la página UsersAndRoles.aspx
. En la parte superior de la página, agregue un control Web etiqueta denominado ActionStatus
y borre su Text
propiedad. Usaremos esta etiqueta para proporcionar comentarios sobre las acciones realizadas, mostrando mensajes como "El usuario Tito se ha agregado al rol Administradores" o "El usuario Jisun se ha quitado del rol Supervisores". Para que estos mensajes destaquen, establezca la propiedad label CssClass
en "Importante".
<p align="center">
<asp:Label ID="ActionStatus" runat="server" CssClass="Important"></asp:Label>
</p>
A continuación, agregue la siguiente definición de clase CSS a la hoja de Styles.css
estilos:
.Important
{
font-size: large;
color: Red;
}
Esta definición de CSS indica al explorador que muestre la etiqueta mediante una fuente grande y roja. En la figura 1 se muestra este efecto a través del Diseñador de Visual Studio.
Figura 1: La propiedad de la CssClass
etiqueta da como resultado una fuente grande y roja (haga clic para ver la imagende tamaño completo)
A continuación, agregue un DropDownList a la página, establezca su ID
propiedad UserList
en y establezca su AutoPostBack
propiedad en True. Usaremos este DropDownList para enumerar todos los usuarios del sistema. Este DropDownList se enlazará a una colección de objetos MembershipUser. Dado que queremos que DropDownList muestre la propiedad UserName del objeto MembershipUser (y úsela como valor de los elementos de lista), establezca las propiedades DataTextField
y DataValueField
DropDownList en "UserName".
Debajo de DropDownList, agregue un repetidor denominado UsersRoleList
. Este repetidor enumerará todos los roles del sistema como una serie de casillas. Defina el ItemTemplate
del repetidor con el marcado declarativo siguiente:
<asp:Repeater ID="UsersRoleList" runat="server">
<ItemTemplate>
<asp:CheckBox runat="server" ID="RoleCheckBox" AutoPostBack="true"
Text='<%# Container.DataItem %>' />
<br />
</ItemTemplate>
</asp:Repeater>
El ItemTemplate
marcado incluye un único control web CheckBox denominado RoleCheckBox
. La propiedad de AutoPostBack
CheckBox se establece en True y la Text
propiedad está enlazada a Container.DataItem
. La razón por la que la sintaxis de enlace de datos es simplemente Container.DataItem
porque el marco roles devuelve la lista de nombres de rol como una matriz de cadenas y es esta matriz de cadenas que se enlazará al repetidor. Una descripción exhaustiva de por qué se usa esta sintaxis para mostrar el contenido de una matriz enlazada a un control web de datos está fuera del ámbito de este tutorial. Para obtener más información sobre este asunto, consulte Enlace de una matriz escalar a un control web de datos.
Llegados a este punto, el marcado declarativo de su interfaz "por usuario" debería tener un aspecto similar al siguiente:
<h3>Manage Roles By User</h3>
<p>
<b>Select a User:</b>
<asp:DropDownList ID="UserList" runat="server" AutoPostBack="True"
DataTextField="UserName" DataValueField="UserName">
</asp:DropDownList>
</p>
<p>
<asp:Repeater ID="UsersRoleList" runat="server">
<ItemTemplate>
<asp:CheckBox runat="server" ID="RoleCheckBox" AutoPostBack="true"
Text='<%# Container.DataItem %>' />
<br />
</ItemTemplate>
</asp:Repeater>
</p>
Ahora estamos listos para escribir el código para enlazar el conjunto de cuentas de usuario a DropDownList y el conjunto de roles en el repetidor. En la clase de código subyacente de la página, agregue un método denominado BindUsersToUserList
y otro denominado BindRolesList
, con el código siguiente:
private void BindUsersToUserList()
{
// Get all of the user accounts
MembershipUserCollection users = Membership.GetAllUsers();
UserList.DataSource = users;
UserList.DataBind();
}
private void BindRolesToList()
{
// Get all of the roles
string[] roles = Roles.GetAllRoles();
UsersRoleList.DataSource = roles;
UsersRoleList.DataBind();
}
El BindUsersToUserList
método recupera todas las cuentas de usuario del sistema a través del Membership.GetAllUsers
método. Esto devuelve un MembershipUserCollection
objeto, que es una colección de MembershipUser
instancias. A continuación, esta colección se enlaza a UserList
DropDownList. Las MembershipUser
instancias que maquillan la colección contienen una variedad de propiedades, como UserName
, Email
, CreationDate
y IsOnline
. Para indicar a DropDownList que muestre el valor de la UserName
propiedad, asegúrese de que las UserList
propiedades y DataValueField
DropDownList DataTextField
se han establecido en "UserName".
Nota:
El método Membership.GetAllUsers
tiene dos sobrecargas: una que no acepta parámetros de entrada y devuelve todos los usuarios y uno que toma valores enteros para el índice de página y el tamaño de página, y devuelve solo el subconjunto especificado de los usuarios. Cuando hay grandes cantidades de cuentas de usuario que se muestran en un elemento de interfaz de usuario paginable, la segunda sobrecarga se puede usar para paginar de forma más eficaz a través de los usuarios, ya que devuelve solo el subconjunto preciso de cuentas de usuario en lugar de todas ellas.
El método BindRolesToList
comienza llamando al Roles
método de la clase GetAllRoles
, que devuelve una matriz de cadenas que contiene los roles del sistema. A continuación, esta matriz de cadenas se enlaza al repetidor.
Por último, es necesario llamar a estos dos métodos cuando la página se carga por primera vez. Agregue el código siguiente al controlador de eventos Page_Load
:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Bind the users and roles
BindUsersToUserList();
BindRolesToList();
}
}
Con este código en vigor, dedique un momento a visitar la página a través de un explorador; la pantalla debe ser similar a la figura 2. Todas las cuentas de usuario se rellenan en la lista desplegable y, debajo, cada rol aparece como una casilla. Dado que establecemos las AutoPostBack
propiedades de DropDownList y CheckBoxes en True, el cambio del usuario seleccionado o la comprobación o desactivación de un rol provoca una devolución de entrada. Sin embargo, no se realiza ninguna acción porque todavía tenemos que escribir código para controlar estas acciones. Abordaremos estas tareas en las dos secciones siguientes.
Figura 2: La página Muestra los usuarios y roles (haga clic para ver la imagen de tamaño completo)
Comprobación de los roles a los que pertenece el usuario seleccionado
Cuando la página se carga por primera vez, o cada vez que el visitante selecciona un nuevo usuario de la lista desplegable, es necesario actualizar las UsersRoleList
casillas de verificación para que una casilla de rol determinada solo esté activada si el usuario seleccionado pertenece a ese rol. Para ello, cree un método denominado CheckRolesForSelectedUser
con el código siguiente:
private void CheckRolesForSelectedUser()
{
// Determine what roles the selected user belongs to
string selectedUserName = UserList.SelectedValue;
string[] selectedUsersRoles = Roles.GetRolesForUser(selectedUserName);
// Loop through the Repeater's Items and check or uncheck the checkbox as needed
foreach (RepeaterItem ri in UsersRoleList.Items)
{
// Programmatically reference the CheckBox
CheckBox RoleCheckBox = ri.FindControl("RoleCheckBox") as CheckBox;
// See if RoleCheckBox.Text is in selectedUsersRoles
if (selectedUsersRoles.Contains<string>(RoleCheckBox.Text))
RoleCheckBox.Checked = true;
else
RoleCheckBox.Checked = false;
}
}
El código anterior comienza por determinar quién es el usuario seleccionado. A continuación, usa el método GetRolesForUser(userName)
de la clase Roles para devolver el conjunto de roles del usuario especificado como una matriz de cadenas. A continuación, se enumeran los elementos del repetidor y se hace referencia mediante programación a CheckBox de RoleCheckBox
cada elemento. CheckBox solo se comprueba si el rol al que corresponde se encuentra dentro de la selectedUsersRoles
matriz de cadenas.
Nota:
La selectedUserRoles.Contains<string>(...)
sintaxis no se compilará si usa ASP.NET versión 2.0. El Contains<string>
método forma parte de la biblioteca LINQ, que es nueva en ASP.NET 3.5. Si sigue usando ASP.NET versión 2.0, use el Array.IndexOf<string>
método en su lugar.
El CheckRolesForSelectedUser
método debe llamarse en dos casos: cuando la página se carga por primera vez y cada vez que se cambia el UserList
índice seleccionado de DropDownList. Por lo tanto, llame a este método desde el Page_Load
controlador de eventos (después de las llamadas a BindUsersToUserList
y BindRolesToList
). Además, cree un controlador de eventos para el evento DropDownList SelectedIndexChanged
y llame a este método desde allí.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Bind the users and roles
BindUsersToUserList();
BindRolesToList();
// Check the selected user's roles
CheckRolesForSelectedUser();
}
}
...
protected void UserList_SelectedIndexChanged(object sender, EventArgs e)
{
CheckRolesForSelectedUser();
}
Con este código en su lugar, puede probar la página a través del explorador. Sin embargo, dado que la UsersAndRoles.aspx
página carece actualmente de la capacidad de asignar usuarios a roles, ningún usuario tiene roles. Vamos a crear la interfaz para asignar usuarios a roles en un momento, por lo que puede tomar mi palabra que este código funciona y comprobar que lo hace más adelante, o bien puede agregar manualmente usuarios a roles insertando registros en la aspnet_UsersInRoles
tabla para probar esta funcionalidad ahora.
Asignación y eliminación de usuarios de roles
Cuando el visitante comprueba o desactiva una casilla en el repetidor UsersRoleList
, es necesario agregar o quitar el usuario seleccionado del rol correspondiente. La propiedad de AutoPostBack
CheckBox se establece actualmente en True, lo que hace que una devolución de entrada se active o desactive una casilla en el Repetidor. En resumen, es necesario crear un controlador de eventos para el evento de CheckChanged
CheckBox. Dado que CheckBox está en un control Repeater, es necesario agregar manualmente la fontanería del controlador de eventos. Para empezar, agregue el controlador de eventos a la clase de código subyacente como método protected
, de la siguiente manera:
protected void RoleCheckBox_CheckChanged(object sender, EventArgs e)
{
}
Volveremos a escribir el código para este controlador de eventos en un momento. Pero primero vamos a completar la fontanería de control de eventos. En checkBox dentro de la ItemTemplate
propiedad repeater, agregue OnCheckedChanged="RoleCheckBox_CheckChanged"
. Esta sintaxis conectan el RoleCheckBox_CheckChanged
controlador de eventos al RoleCheckBox
evento de CheckedChanged
.
<asp:CheckBox runat="server" ID="RoleCheckBox"
AutoPostBack="true"
Text='<%# Container.DataItem %>'
OnCheckedChanged="RoleCheckBox_CheckChanged" />
Nuestra tarea final es completar el controlador de RoleCheckBox_CheckChanged
eventos. Es necesario empezar haciendo referencia al control CheckBox que generó el evento porque esta instancia de CheckBox nos indica qué rol se ha comprobado o desmarcado a través de sus Text
propiedades y Checked
. Utilizando esta información junto con el UserName del usuario seleccionado, añadimos o eliminamos al usuario del rol a través de la Roles
de la AddUserToRole
de la clase o método RemoveUserFromRole
.
protected void RoleCheckBox_CheckChanged(object sender, EventArgs e)
{
// Reference the CheckBox that raised this event
CheckBox RoleCheckBox = sender as CheckBox;
// Get the currently selected user and role
string selectedUserName = UserList.SelectedValue;
string roleName = RoleCheckBox.Text;
// Determine if we need to add or remove the user from this role
if (RoleCheckBox.Checked)
{
// Add the user to the role
Roles.AddUserToRole(selectedUserName, roleName);
// Display a status message
ActionStatus.Text = string.Format("User {0} was added to role {1}.", selectedUserName, roleName);
}
else
{
// Remove the user from the role
Roles.RemoveUserFromRole(selectedUserName, roleName);
// Display a status message
ActionStatus.Text = string.Format("User {0} was removed from role {1}.", selectedUserName, roleName);
}
}
El código anterior comienza haciendo referencia mediante programación a la casilla que generó el evento, que está disponible a través del sender
parámetro input. Si la casilla está activada, el usuario seleccionado se agrega al rol especificado; de lo contrario, se quitan del rol. En cualquier caso, la ActionStatus
etiqueta muestra un mensaje que resume la acción que acaba de realizar.
Tómese un momento para probar esta página a través de un navegador. Seleccione el usuario Tito y, a continuación, agregue Tito a los roles Administradores y Supervisores.
Figura 3: Se ha agregado Tito a los roles administradores y supervisores (haga clic para ver la imagende tamaño completo)
A continuación, seleccione el usuario Bruce en la lista desplegable. Hay un postback y las casillas del repetidor se actualizan a través de CheckRolesForSelectedUser
. Puesto que Bruce aún no pertenece a ningún rol, las dos casillas están desactivadas. A continuación, agregue Bruce al rol Supervisores.
Figura 4: Se ha agregado Bruce al rol supervisores (haga clic para ver la imagen de tamaño completo)
Para comprobar aún más la funcionalidad del CheckRolesForSelectedUser
método, seleccione un usuario distinto de Tito o Bruce. Observe cómo las casillas se desactivan automáticamente, lo que indica que no pertenecen a ningún rol. Volver al principio Las casillas Administradores y Supervisores deben estar activadas.
Paso 2: Compilar la interfaz de usuario "Por roles"
En este momento hemos completado la interfaz "by users" y estamos listos para empezar a abordar la interfaz "por roles". La interfaz "por roles" solicita al usuario que seleccione un rol en una lista desplegable y, a continuación, muestra el conjunto de usuarios que pertenecen a ese rol en GridView.
Agregue otro control DropDownList a la página UsersAndRoles.aspx
. Coloque este debajo del control Repeater, asígnelo RoleList
el nombre y establezca su AutoPostBack
propiedad en True. Debajo de eso, agregue un control GridView y asígnele el nombre RolesUserList
. Esta clase GridView enumerará los usuarios que pertenecen al rol seleccionado. Establezca la propiedad de AutoGenerateColumns
GridView en False, agregue un TemplateField a la colección de Columns
la cuadrícula y establezca su HeaderText
propiedad en "Users". Defina TemplateField ItemTemplate
para que muestre el valor de la expresión Container.DataItem
de enlace de datos en la Text
propiedad de una etiqueta denominada UserNameLabel
.
Después de agregar y configurar GridView, el marcado declarativo de la interfaz "por rol" debe ser similar al siguiente:
<h3>Manage Users By Role</h3>
<p>
<b>Select a Role:</b>
<asp:DropDownList ID="RoleList" runat="server" AutoPostBack="true"></asp:DropDownList>
</p>
<p> <asp:GridView ID="RolesUserList" runat="server" AutoGenerateColumns="false"
EmptyDataText="No users belong to this role.">
<Columns>
<asp:TemplateField HeaderText="Users">
<ItemTemplate>
<asp:Label runat="server" id="UserNameLabel"
Text='<%# Container.DataItem %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView> </p>
Es necesario rellenar DropDownList RoleList
con el conjunto de roles del sistema. Para ello, actualice el BindRolesToList
método para que se enlace la matriz de cadenas devuelta por el Roles.GetAllRoles
método a RolesList
DropDownList (así como el repetidor UsersRoleList
).
private void BindRolesToList()
{
// Get all of the roles
string[] roles = Roles.GetAllRoles();
UsersRoleList.DataSource = roles;
UsersRoleList.DataBind();
RoleList.DataSource = roles;
RoleList.DataBind();
}
Se han agregado las dos últimas líneas del BindRolesToList
método para enlazar el conjunto de roles al RoleList
control DropDownList. En la figura 5 se muestra el resultado final cuando se ve a través de un explorador: una lista desplegable rellenada con los roles del sistema.
Figura 5: Los roles se muestran en la DropDownList RoleList
(haga clic para ver la imagen de tamaño completo)
Mostrar los usuarios que pertenecen al rol seleccionado
Cuando la página se carga por primera vez, o cuando se selecciona un nuevo rol en DropDownList RoleList
, es necesario mostrar la lista de usuarios que pertenecen a ese rol en GridView. Cree un método denominado DisplayUsersBelongingToRole
con el código siguiente:
private void DisplayUsersBelongingToRole()
{
// Get the selected role
string selectedRoleName = RoleList.SelectedValue;
// Get the list of usernames that belong to the role
string[] usersBelongingToRole = Roles.GetUsersInRole(selectedRoleName);
// Bind the list of users to the GridView
RolesUserList.DataSource = usersBelongingToRole;
RolesUserList.DataBind();
}
Este método comienza obteniendo el rol seleccionado de RoleList
DropDownList. A continuación, usa el Roles.GetUsersInRole(roleName)
método para recuperar una matriz de cadenas de los UserNames de los usuarios que pertenecen a ese rol. A continuación, esta matriz se enlaza a RolesUserList
GridView.
Este método debe llamarse en dos circunstancias: cuando la página se carga inicialmente y cuando cambia el rol seleccionado en DropDownList RoleList
. Por lo tanto, actualice el Page_Load
controlador de eventos para que este método se invoque después de la llamada a CheckRolesForSelectedUser
. A continuación, cree un controlador de eventos para el RoleList
evento de SelectedIndexChanged
y llame a este método desde allí también.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Bind the users and roles
BindUsersToUserList();
BindRolesToList();
// Check the selected user's roles
CheckRolesForSelectedUser();
// Display those users belonging to the currently selected role
DisplayUsersBelongingToRole();
}
}
...
protected void RoleList_SelectedIndexChanged(object sender, EventArgs e)
{
DisplayUsersBelongingToRole();
}
Con este código implementado, GridView RolesUserList
debe mostrar los usuarios que pertenecen al rol seleccionado. Como se muestra en la figura 6, el rol Supervisores consta de dos miembros: Bruce y Tito.
Figura 6: GridView enumera los usuarios que pertenecen al rol seleccionado (haga clic para ver la imagende tamaño completo)
Quitar usuarios del rol seleccionado
Vamos a aumentar GridView RolesUserList
para que incluya una columna de botones "Quitar". Al hacer clic en el botón "Quitar" de un usuario determinado, se quitarán de ese rol.
Empiece agregando un campo de botón Eliminar a GridView. Haga que este campo aparezca como el más archivado a la izquierda y cambie su DeleteText
propiedad de "Delete" (valor predeterminado) a "Remove".
Figura 7: Agregar el botón "Quitar" a GridView (Haga clic para ver la imagende tamaño completo)
Cuando se hace clic en el botón "Quitar" se produce una devolución de postback y se genera el evento de RowDeleting
GridView. Es necesario crear un controlador de eventos para este evento y escribir código que quite al usuario del rol seleccionado. A continuación, cree el controlador de eventos y agregue el código siguiente:
protected void RolesUserList_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
// Get the selected role
string selectedRoleName = RoleList.SelectedValue;
// Reference the UserNameLabel
Label UserNameLabel = RolesUserList.Rows[e.RowIndex].FindControl("UserNameLabel") as Label;
// Remove the user from the role
Roles.RemoveUserFromRole(UserNameLabel.Text, selectedRoleName);
// Refresh the GridView
DisplayUsersBelongingToRole();
// Display a status message
ActionStatus.Text = string.Format("User {0} was removed from role {1}.", UserNameLabel.Text, selectedRoleName);
}
El código comienza por determinar el nombre del rol seleccionado. A continuación, hace referencia mediante programación al UserNameLabel
control de la fila cuyo botón "Quitar" se hizo clic para determinar el nombre de usuario del usuario que se va a quitar. A continuación, el usuario se quita del rol a través de una llamada al Roles.RemoveUserFromRole
método. A RolesUserList
continuación, GridView se actualiza y se muestra un mensaje a través del ActionStatus
control Etiqueta.
Nota:
El botón "Quitar" no requiere ninguna confirmación del usuario antes de quitar el usuario del rol. Te invitamos a agregar algún nivel de confirmación de usuario. Una de las formas más fáciles de confirmar una acción es a través de un cuadro de diálogo confirmar del lado cliente. Para obtener más información sobre esta técnica, vea Agregar confirmación del lado cliente al eliminar.
En la figura 8 se muestra la página después de que el usuario Tito se haya quitado del grupo Supervisores.
Figura 8: Alas, Tito ya no es supervisor (haga clic para ver la imagen de tamaño completo)
Agregar nuevos usuarios al rol seleccionado
Junto con la eliminación de usuarios del rol seleccionado, el visitante a esta página también debería poder agregar un usuario al rol seleccionado. La mejor interfaz para agregar un usuario al rol seleccionado depende del número de cuentas de usuario que espera tener. Si su sitio web hospedará solo unas docenas de cuentas de usuario o menos, puede usar un DropDownList aquí. Si puede haber miles de cuentas de usuario, querrá incluir una interfaz de usuario que permita al visitante paginar a través de las cuentas, buscar una cuenta determinada o filtrar las cuentas de usuario de alguna otra manera.
Para esta página, vamos a usar una interfaz muy sencilla que funcione independientemente del número de cuentas de usuario del sistema. Es decir, usaremos un TextBox, que pide al visitante que escriba el nombre de usuario del usuario que quiere agregar al rol seleccionado. Si no existe ningún usuario con ese nombre o si el usuario ya es miembro del rol, mostraremos un mensaje en Etiqueta ActionStatus
. Pero si el usuario existe y no es miembro del rol, los agregaremos al rol y actualizaremos la cuadrícula.
Agregue un cuadro de texto y un botón debajo de GridView. Establezca el control TextBox ID
en UserNameToAddToRole
y establezca las propiedades ID
y Text
del botón en AddUserToRoleButton
y "Agregar usuario a rol", respectivamente.
<p>
<b>UserName:</b>
<asp:TextBox ID="UserNameToAddToRole" runat="server"></asp:TextBox>
<br />
<asp:Button ID="AddUserToRoleButton" runat="server" Text="Add User to Role" />
</p>
Cree un controlador de eventos Click
para el botón AddUserToRoleButton
y agregue el código siguiente:
protected void AddUserToRoleButton_Click(object sender, EventArgs e)
{
// Get the selected role and username
string selectedRoleName = RoleList.SelectedValue;
string userNameToAddToRole = UserNameToAddToRole.Text;
// Make sure that a value was entered
if (userNameToAddToRole.Trim().Length == 0)
{
ActionStatus.Text = "You must enter a username in the textbox.";
return;
}
// Make sure that the user exists in the system
MembershipUser userInfo = Membership.GetUser(userNameToAddToRole);
if (userInfo == null)
{
ActionStatus.Text = string.Format("The user {0} does not exist in the system.", userNameToAddToRole);
return;
}
// Make sure that the user doesn't already belong to this role
if (Roles.IsUserInRole(userNameToAddToRole, selectedRoleName))
{
ActionStatus.Text = string.Format("User {0} already is a member of role {1}.", userNameToAddToRole, selectedRoleName);
return;
}
// If we reach here, we need to add the user to the role
Roles.AddUserToRole(userNameToAddToRole, selectedRoleName);
// Clear out the TextBox
UserNameToAddToRole.Text = string.Empty;
// Refresh the GridView
DisplayUsersBelongingToRole();
// Display a status message
ActionStatus.Text = string.Format("User {0} was added to role {1}.", userNameToAddToRole, selectedRoleName); }
La mayoría del código del Click
controlador de eventos realiza varias comprobaciones de validación. Garantiza que el visitante proporcionó un nombre de usuario en TextBox UserNameToAddToRole
, que el usuario existe en el sistema y que aún no pertenecen al rol seleccionado. Si se produce un error en cualquiera de estas comprobaciones, se muestra un mensaje adecuado en ActionStatus
y se cierra el controlador de eventos. Si se pasan todas las comprobaciones, el usuario se agrega al rol a través del Roles.AddUserToRole
método. Después de eso, se borra la propiedad TextBox Text
, se actualiza GridView y la ActionStatus
etiqueta muestra un mensaje que indica que el usuario especificado se agregó correctamente al rol seleccionado.
Nota:
Para asegurarse de que el usuario especificado aún no pertenece al rol seleccionado, usamos el Roles.IsUserInRole(userName, roleName)
método, que devuelve un valor booleano que indica si userName es miembro de roleName. Usaremos este método de nuevo en el siguiente tutorial cuando examinemos la autorización basada en roles.
Visite la página a través de un explorador y seleccione el rol Supervisors en DropDownList RoleList
. Intente escribir un nombre de usuario no válido: debería ver un mensaje que explique que el usuario no existe en el sistema.
Figura 9: No se puede agregar un usuario no existente a un rol (haga clic para ver la imagende tamaño completo)
Ahora intente agregar un usuario válido. Continúe y vuelva a agregar Tito al rol supervisores.
Figura 10: Tito es una vez más supervisor! (Haga clic para ver la imagen a tamaño completo.)
Paso 3: Actualización cruzada de las interfaces "By User" y "By Role"
La UsersAndRoles.aspx
página ofrece dos interfaces distintas para administrar usuarios y roles. Actualmente, estas dos interfaces actúan independientemente entre sí, por lo que es posible que un cambio realizado en una interfaz no se refleje inmediatamente en la otra. Por ejemplo, imagine que el visitante de la página selecciona el rol Supervisores de DropDownList RoleList
, que enumera Bruce y Tito como sus miembros. A continuación, el visitante selecciona Tito en DropDownList UserList
, que comprueba las casillas Administradores y Supervisores en el UsersRoleList
Repetidor. Si el visitante desactiva el rol supervisor del repetidor, Tito se quita del rol supervisor, pero esta modificación no se refleja en la interfaz "por rol". GridView seguirá mostrando a Tito como miembro del rol Supervisores.
Para corregir esto, es necesario actualizar GridView siempre que se compruebe o desactive un rol del UsersRoleList
repetidor. Del mismo modo, es necesario actualizar repeater cada vez que se quita o se agrega un usuario a un rol de la interfaz "by role".
El repetidor de la interfaz "por usuario" se actualiza llamando al CheckRolesForSelectedUser
método. La interfaz "por rol" se puede modificar en el RolesUserList
controlador de eventos de RowDeleting
GridView y en el AddUserToRoleButton
controlador de eventos del Click
botón. Por lo tanto, es necesario llamar al CheckRolesForSelectedUser
método desde cada uno de estos métodos.
protected void RolesUserList_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
... Code removed for brevity ...
// Refresh the "by user" interface
CheckRolesForSelectedUser();
}
protected void AddUserToRoleButton_Click(object sender, EventArgs e)
{
... Code removed for brevity ...
// Refresh the "by user" interface
CheckRolesForSelectedUser();
}
Del mismo modo, GridView en la interfaz "por rol" se actualiza llamando al DisplayUsersBelongingToRole
método y la interfaz "by user" se modifica a través del RoleCheckBox_CheckChanged
controlador de eventos. Por lo tanto, es necesario llamar al DisplayUsersBelongingToRole
método desde este controlador de eventos.
protected void RoleCheckBox_CheckChanged(object sender, EventArgs e)
{
... Code removed for brevity...
// Refresh the "by role" interface
DisplayUsersBelongingToRole();
}
Con estos cambios de código menores, las interfaces "por usuario" y "por rol" ahora se actualizan correctamente. Para comprobarlo, visite la página a través de un explorador y seleccione Tito y Supervisores en y UserList
RoleList
DropDownLists, respectivamente. Tenga en cuenta que, a medida que desactive el rol Supervisores para Tito desde el Repetidor en la interfaz "por usuario", Tito se quita automáticamente de GridView en la interfaz "por rol". Al volver a agregar Tito al rol Supervisores desde la interfaz "por rol" se vuelve a comprobar automáticamente la casilla Supervisores en la interfaz "by user".
Paso 4: Personalizar CreateUserWizard para incluir un paso "Especificar roles"
En el tutorial Creación de cuentas de usuario hemos visto cómo usar el control Web CreateUserWizard para proporcionar una interfaz para crear una nueva cuenta de usuario. El control CreateUserWizard se puede usar de una de estas dos maneras:
- Como medio para que los visitantes creen su propia cuenta de usuario en el sitio, y
- Como medio para que los administradores creen nuevas cuentas
En el primer caso de uso, un visitante llega al sitio y rellena el CreateUserWizard, escribiendo su información para registrarse en el sitio. En el segundo caso, un administrador crea una nueva cuenta para otra persona.
Cuando un administrador crea una cuenta para otra persona, puede resultar útil permitir al administrador especificar a qué roles pertenece la nueva cuenta de usuario. En el tutorial Almacenarinformación de usuario adicional, vimos cómo personalizar CreateUserWizard agregando más WizardSteps
. Veamos cómo agregar un paso adicional a CreateUserWizard para especificar los roles del nuevo usuario.
Abra la CreateUserWizardWithRoles.aspx
página y agregue un control CreateUserWizard denominado RegisterUserWithRoles
. Establezca la propiedad del ContinueDestinationPageUrl
control en "~/Default.aspx". Dado que la idea aquí es que un administrador usará este control CreateUserWizard para crear nuevas cuentas de usuario, establezca la propiedad del LoginCreatedUser
control en False. Esta LoginCreatedUser
propiedad especifica si el visitante inicia sesión automáticamente como el usuario recién creado y el valor predeterminado es True. Lo establecemos en False porque cuando un administrador crea una nueva cuenta, queremos mantenerla iniciada como él mismo.
A continuación, seleccione "Agregar o quitar WizardSteps
..." opción de la etiqueta inteligente CreateUserWizard y agregue un nuevo WizardStep
, estableciendo en ID
SpecifyRolesStep
. Mueva el SpecifyRolesStep WizardStep
para que llegue después del paso "Suscribirse a su nueva cuenta", pero antes del paso "Completar". Establezca la propiedad de en WizardStep
Title
"Especificar roles", su StepType
propiedad Step
en y su AllowReturn
propiedad en False.
Figura 11: Agregar "Especificar roles" WizardStep
a CreateUserWizard (Haga clic para ver la imagen de tamaño completo)
Después de este cambio, el marcado declarativo de CreateUserWizard debe ser similar al siguiente:
<asp:CreateUserWizard ID="RegisterUserWithRoles" runat="server"
ContinueDestinationPageUrl="~/Default.aspx" LoginCreatedUser="False">
<WizardSteps>
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
</asp:CreateUserWizardStep>
<asp:WizardStep ID="SpecifyRolesStep" runat="server" StepType="Step"
Title="Specify Roles" AllowReturn="False">
</asp:WizardStep>
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
</asp:CompleteWizardStep>
</WizardSteps>
</asp:CreateUserWizard>
En "Especificar roles", WizardStep
agregue un CheckBoxList denominado RoleList
. Este CheckBoxList enumerará los roles disponibles, lo que permite a la persona que visita la página comprobar a qué roles pertenece el usuario recién creado.
Nos quedamos con dos tareas de codificación: primero debemos rellenar CheckBoxList RoleList
con los roles del sistema; en segundo lugar, es necesario agregar el usuario creado a los roles seleccionados cuando el usuario pasa del paso "Especificar roles" al paso "Completar". Podemos realizar la primera tarea en el controlador de Page_Load
eventos. El código siguiente hace referencia mediante programación a CheckBox RoleList
en la primera visita a la página y enlaza los roles del sistema a él.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Reference the SpecifyRolesStep WizardStep
WizardStep SpecifyRolesStep = RegisterUserWithRoles.FindControl("SpecifyRolesStep") as WizardStep;
// Reference the RoleList CheckBoxList
CheckBoxList RoleList = SpecifyRolesStep.FindControl("RoleList") as CheckBoxList;
// Bind the set of roles to RoleList
RoleList.DataSource = Roles.GetAllRoles();
RoleList.DataBind();
}
}
El código anterior debe ser familiar. En el tutorial Almacenarinformación adicional de usuario hemos usado dos FindControl
instrucciones para hacer referencia a un control web desde un personalizado WizardStep
. Y el código que enlaza los roles a CheckBoxList se tomó anteriormente en este tutorial.
Para realizar la segunda tarea de programación, es necesario saber cuándo se ha completado el paso "Especificar roles". Recuerde que CreateUserWizard tiene un ActiveStepChanged
evento, que se desencadena cada vez que el visitante navega de un paso a otro. Aquí podemos determinar si el usuario ha alcanzado el paso "Completar"; si es así, es necesario agregar el usuario a los roles seleccionados.
Cree un controlador de eventos para el evento de ActiveStepChanged
y agregue el código siguiente al controlador:
protected void RegisterUserWithRoles_ActiveStepChanged(object sender, EventArgs e)
{
// Have we JUST reached the Complete step?
if (RegisterUserWithRoles.ActiveStep.Title == "Complete")
{
// Reference the SpecifyRolesStep WizardStep
WizardStep SpecifyRolesStep = RegisterUserWithRoles.FindControl("SpecifyRolesStep") as WizardStep;
// Reference the RoleList CheckBoxList
CheckBoxList RoleList = SpecifyRolesStep.FindControl("RoleList") as CheckBoxList;
// Add the checked roles to the just-added user
foreach (ListItem li in RoleList.Items)
{
if (li.Selected)
Roles.AddUserToRole(RegisterUserWithRoles.UserName, li.Text);
}
}
}
Si el usuario acaba de alcanzar el paso "Completado", el controlador de eventos enumera los elementos de RoleList
CheckBoxList y el usuario recién creado se asigna a los roles seleccionados.
Ahora pruebe esta página a través de un explorador. El primer paso de CreateUserWizard es el paso estándar "Suscribirse a su nueva cuenta", que solicita el nombre de usuario, la contraseña, el correo electrónico y otra información clave del nuevo usuario. Escriba la información para crear un nuevo usuario denominado Wanda.
Figura 12: Crear un nuevo usuario denominado Wanda (haga clic para ver la imagende tamaño completo)
Haga clic en el botón Crear usuario. CreateUserWizard llama internamente al Membership.CreateUser
método, crea la nueva cuenta de usuario y, a continuación, avanza al paso siguiente, "Especificar roles". Aquí se enumeran los roles del sistema. Active la casilla Supervisores y haga clic en Siguiente.
Figura 13: Hacer que Wanda sea miembro del rol supervisores (haga clic para ver la imagende tamaño completo)
Al hacer clic en Siguiente, se produce un postback y se actualiza el ActiveStep
al paso "Completar". En el ActiveStepChanged
controlador de eventos, la cuenta de usuario creada recientemente se asigna al rol Supervisores. Para comprobarlo, vuelva a la UsersAndRoles.aspx
página y seleccione Supervisors en DropDownList RoleList
. Como se muestra en la figura 14, los supervisores ahora están formados por tres usuarios: Bruce, Tito y Wanda.
Figura 14: Bruce, Tito y Wanda son Todos los Supervisores (Haga clic para ver la imagende tamaño completo)
Resumen
El marco roles ofrece métodos para recuperar información sobre los roles y métodos de un usuario determinado para determinar qué usuarios pertenecen a un rol especificado. Además, hay varios métodos para agregar y quitar uno o varios usuarios a uno o varios roles. En este tutorial nos centramos en solo dos de estos métodos: AddUserToRole
y RemoveUserFromRole
. Hay variantes adicionales diseñadas para agregar varios usuarios a un solo rol y asignar varios roles a un único usuario.
En este tutorial también se ha incluido un vistazo a la extensión del control CreateUserWizard para incluir para WizardStep
especificar los roles del usuario recién creados. Este paso podría ayudar a un administrador a simplificar el proceso de creación de cuentas de usuario para nuevos usuarios.
En este punto hemos visto cómo crear y eliminar roles y cómo agregar y quitar usuarios de roles. Pero todavía tenemos que examinar la aplicación de la autorización basada en roles. En el siguiente tutorial veremos cómo definir reglas de autorización de direcciones URL por rol, así como cómo limitar la funcionalidad de nivel de página en función de los roles del usuario que ha iniciado sesión actualmente.
¡Feliz programación!
Lecturas adicionales
Para obtener más información sobre los temas tratados en este tutorial, consulte los siguientes recursos:
- Visión general de la herramienta de administración de sitios web ASP.NET
- Examinar ASP. Pertenencia, roles y perfil de NET
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, formador 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...
Muchos revisores han evaluado esta serie de tutoriales. El revisor principal de este tutorial ha sido Teresa Murphy. ¿Le interesaría revisar mis próximos artículos de MSDN? Si es así, escríbame a mitchell@4GuysFromRolla.com