Назначение ролей пользователям (C#)
Примечание
С момента написания этой статьи поставщики членства ASP.NET были заменены ASP.NET Identity. Мы настоятельно рекомендуем обновить приложения для использования платформы ASP.NET Identity , а не поставщиков членства, которые были представлены на момент написания этой статьи. ASP.NET Identity имеет ряд преимуществ по сравнению с системой членства ASP.NET, включая :
- более высокая производительность;
- Улучшенная расширяемость и тестируемость
- Поддержка OAuth, OpenID Connect и двухфакторной проверки подлинности
- Поддержка удостоверений на основе утверждений
- Улучшенное взаимодействие с ASP.Net Core
Скачать код или скачать PDF-файл
В этом руководстве мы создадим две страницы ASP.NET, которые помогут управлять пользователями, принадлежащими к тем или иным ролям. Первая страница содержит средства, которые позволяют узнать, какие пользователи принадлежат к определенной роли, к каким ролям принадлежит конкретный пользователь, а также возможность назначить или удалить определенного пользователя из определенной роли. На второй странице мы добавим элемент управления CreateUserWizard, чтобы он включает шаг для указания ролей, к которым принадлежит только что созданный пользователь. Это полезно в сценариях, когда администратор может создавать новые учетные записи пользователей.
Введение
В предыдущем руководстве рассматривались платформа Roles и SqlRoleProvider
; мы узнали Roles
, как использовать класс для создания, извлечения и удаления ролей. Помимо создания и удаления ролей, необходимо иметь возможность назначать или удалять пользователей из роли. К сожалению, ASP.NET не поставляются с веб-элементами управления для управления пользователями, принадлежащими к тем или иным ролям. Вместо этого мы должны создать собственные страницы ASP.NET для управления этими связями. Хорошей новостью является то, что добавлять и удалять пользователей в роли довольно просто. Класс Roles
содержит несколько методов для добавления одного или нескольких пользователей в одну или несколько ролей.
В этом руководстве мы создадим две страницы ASP.NET, которые помогут управлять пользователями, принадлежащими к тем или иным ролям. Первая страница содержит средства, которые позволяют узнать, какие пользователи принадлежат к определенной роли, к каким ролям принадлежит конкретный пользователь, а также возможность назначить или удалить определенного пользователя из определенной роли. На второй странице мы добавим элемент управления CreateUserWizard, чтобы он включает шаг для указания ролей, к которым принадлежит только что созданный пользователь. Это полезно в сценариях, когда администратор может создавать новые учетные записи пользователей.
Приступим к работе!
Список пользователей, принадлежащих к тем или иным ролям
Первым делом в этом руководстве следует создать веб-страницу, на которой пользователям могут быть назначены роли. Прежде чем мы рассмотрим, как назначать пользователям роли, давайте сначала сосредоточимся на том, как определить, какие пользователи принадлежат к тем или иным ролям. Существует два способа отображения этой информации: "по роли" или "по пользователю". Мы можем разрешить посетителю выбрать роль, а затем показать ему всех пользователей, принадлежащих к роли (отображение "по роли"), или предложить посетителю выбрать пользователя, а затем показать ему роли, назначенные ему (отображение "по пользователю").
Представление "по роли" полезно в тех случаях, когда посетитель хочет узнать набор пользователей, принадлежащих к определенной роли; Представление "по пользователю" идеально подходит, когда посетителю необходимо знать роли конкретного пользователя. Давайте добавим, что наша страница содержит интерфейсы "по роли" и "по пользователю".
Начнем с создания интерфейса "по пользователю". Этот интерфейс будет состоять из раскрывающегося списка и списка флажков. Раскрывающийся список будет заполнен набором пользователей в системе; флажки будут перечислять роли. При выборе пользователя из раскрывающегося списка будут проверка роли, к которой он принадлежит. Пользователь, посещающий страницу, может проверка или снять флажки, чтобы добавить или удалить выбранного пользователя из соответствующих ролей.
Примечание
Использование раскрывающегося списка для перечисления учетных записей пользователей не является идеальным выбором для веб-сайтов, где могут быть сотни учетных записей пользователей. Раскрывающийся список позволяет пользователю выбрать один элемент из относительно короткого списка параметров. Он быстро становится громоздким по мере роста количества элементов списка. Если вы создаете веб-сайт, который будет иметь потенциально большое количество учетных записей пользователей, вы можете рассмотреть возможность использования альтернативного пользовательского интерфейса, например страничного GridView или фильтруемого интерфейса, который предлагает посетителю выбрать букву, а затем отображает только тех пользователей, имя пользователя которых начинается с выбранной буквы.
Шаг 1. Создание пользовательского интерфейса "По пользователю"
Откройте страницу UsersAndRoles.aspx
. В верхней части страницы добавьте веб-элемент управления Label с именем ActionStatus
и очистите его Text
свойство. Мы будем использовать эту метку, чтобы оставить отзыв о выполненных действиях, отображая такие сообщения, как "Пользователь Тито был добавлен в роль администраторов" или "Пользователь Jisun был удален из роли "Супервизоры". Чтобы выделить эти сообщения, задайте для свойства Label CssClass
значение "Важно".
<p align="center">
<asp:Label ID="ActionStatus" runat="server" CssClass="Important"></asp:Label>
</p>
Затем добавьте в таблицу стилей следующее Styles.css
определение класса CSS:
.Important
{
font-size: large;
color: Red;
}
Это определение CSS предписывает браузеру отобразить метку с помощью большого красного шрифта. На рисунке 1 показан этот эффект с помощью Designer Visual Studio.
Рис. 1. Свойство метки CssClass
приводит к большому красному шрифту (щелкните для просмотра полноразмерного изображения)
Затем добавьте dropDownList на страницу, присвойте свойству ID
UserList
значение , а свойству — AutoPostBack
значение True. Мы будем использовать этот список DropDownList для вывода списка всех пользователей в системе. Этот DropDownList будет привязан к коллекции объектов MembershipUser. Так как мы хотим, чтобы DropDownList отображал свойство UserName объекта MembershipUser (и использовал его в качестве значения элементов списка), задайте для свойств DropDownList DataTextField
и DataValueField
значение UserName.
Под DropDownList добавьте повторитель с именем UsersRoleList
. Этот повторитель выдаст список всех ролей в системе в виде последовательности флажков. Определите объект Repeater с помощью следующей декларативной ItemTemplate
разметки:
<asp:Repeater ID="UsersRoleList" runat="server">
<ItemTemplate>
<asp:CheckBox runat="server" ID="RoleCheckBox" AutoPostBack="true"
Text='<%# Container.DataItem %>' />
<br />
</ItemTemplate>
</asp:Repeater>
Разметка ItemTemplate
включает в себя один веб-элемент управления CheckBox с именем RoleCheckBox
. Свойство CheckBox AutoPostBack
имеет значение True, а Text
свойство привязано к Container.DataItem
. Причина синтаксиса привязки данных заключается в том, Container.DataItem
что платформа ролей возвращает список имен ролей в виде массива строк, и именно этот массив строк будет привязан к Repeater. Подробное описание того, почему этот синтаксис используется для отображения содержимого массива, привязанного к веб-элементу управления данными, выходит за рамки область этого руководства. Дополнительные сведения по этому вопросу см. в статье Привязка скалярного массива к веб-элементу управления данных.
На этом этапе декларативная разметка интерфейса "by user" должна выглядеть примерно так:
<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>
Теперь мы готовы написать код для привязки набора учетных записей пользователей к DropDownList и набора ролей к Repeater. В классе кода программной части страницы добавьте метод с именем BindUsersToUserList
и еще один с именем BindRolesList
, используя следующий код:
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();
}
Метод BindUsersToUserList
извлекает все учетные записи пользователей в системе с помощью Membership.GetAllUsers
метода . Возвращает объектMembershipUserCollection
, который представляет собой коллекцию MembershipUser
экземпляров . Затем эта коллекция привязывается к UserList
DropDownList. Экземпляры MembershipUser
, которые содержат коллекцию, содержат различные свойства, такие как UserName
, Email
, CreationDate
и IsOnline
. Чтобы указать DropDownList отобразить значение UserName
свойства, убедитесь, что UserList
свойства DropDownList DataTextField
и DataValueField
имеют значение UserName.
Примечание
Метод Membership.GetAllUsers
имеет две перегрузки: одна, которая не принимает входные параметры и возвращает всех пользователей, а другая принимает целочисленные значения для индекса страницы и размера страницы и возвращает только указанное подмножество пользователей. При наличии большого количества учетных записей пользователей, отображаемых в элементе пользовательского интерфейса, доступном для страниц, можно использовать вторую перегрузку для более эффективного перебора пользователей, так как она возвращает только точное подмножество учетных записей пользователей, а не все из них.
Метод BindRolesToList
начинается с вызова Roles
метода класса GetAllRoles
, который возвращает массив строк, содержащий роли в системе. Затем этот массив строк привязывается к repeater.
Наконец, необходимо вызвать эти два метода при первой загрузке страницы. Добавьте следующий код в обработчик событий Page_Load
.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Bind the users and roles
BindUsersToUserList();
BindRolesToList();
}
}
Используя этот код, посетите страницу через браузер; ваш экран должен выглядеть примерно так, как на рисунке 2. Все учетные записи пользователей заполняются в раскрывающемся списке, и под ним каждая роль отображается как флажок. Так как для свойств DropDownList и CheckBoxes задано AutoPostBack
значение True, изменение выбранного пользователя или проверка или отмена флажка роли приводит к обратной отправке. Однако никаких действий не выполняется, так как нам еще предстоит написать код для обработки этих действий. Мы рассмотрим эти задачи в следующих двух разделах.
Рис. 2. На странице отображаются пользователи и роли (щелкните, чтобы просмотреть полноразмерное изображение)
Проверка ролей, к которому принадлежит выбранный пользователь
При первой загрузке страницы или при выборе посетителем нового пользователя из раскрывающегося списка необходимо обновить UsersRoleList
флажки таким образом, чтобы флажок определенной роли был установлен только в том случае, если выбранный пользователь принадлежит этой роли. Для этого создайте метод с именем CheckRolesForSelectedUser
со следующим кодом:
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;
}
}
Приведенный выше код начинается с определения выбранного пользователя. Затем он использует метод класса GetRolesForUser(userName)
Roles для возврата набора ролей указанного пользователя в виде массива строк. Далее перечисляются элементы Repeater, и на элемент CheckBox каждого элемента RoleCheckBox
создается программная ссылка. Флажок CheckBox проверяется только в том случае, если роль, которая ему соответствует, содержится в массиве selectedUsersRoles
строк.
Примечание
Синтаксис selectedUserRoles.Contains<string>(...)
не будет компилироваться, если используется ASP.NET версии 2.0. Метод Contains<string>
является частью библиотеки LINQ, которая является новой для ASP.NET 3.5. Если вы по-прежнему используете ASP.NET версии 2.0, используйте Array.IndexOf<string>
метод .
Метод CheckRolesForSelectedUser
необходимо вызывать в двух случаях: при первой загрузке страницы и при изменении выбранного UserList
индекса DropDownList. Поэтому вызовите этот метод из обработчика Page_Load
событий (после вызовов BindUsersToUserList
и BindRolesToList
). Кроме того, создайте обработчик событий для события DropDownList SelectedIndexChanged
и вызовите этот метод.
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();
}
С помощью этого кода можно протестировать страницу с помощью браузера. Тем не менее, так как на UsersAndRoles.aspx
странице в настоящее время нет возможности назначать пользователям роли, у пользователей нет ролей. Мы создадим интерфейс для назначения пользователям ролей через некоторое время, чтобы вы могли либо поверить на слово, что этот код работает, и убедиться, что он это делает позже, либо вручную добавить пользователей к ролям, вставив записи в aspnet_UsersInRoles
таблицу, чтобы проверить эту функциональность сейчас.
Назначение и удаление пользователей из ролей
Когда посетитель проверяет или снимает флажок CheckBox в UsersRoleList
repeater, необходимо добавить или удалить выбранного пользователя из соответствующей роли. Свойство CheckBox AutoPostBack
в настоящее время имеет значение True, что приводит к обратной отправке при каждом снятии флажка CheckBox в повторителе. Короче говоря, нам нужно создать обработчик событий для события CheckBox CheckChanged
. Так как CheckBox находится в элементе управления Repeater, необходимо вручную добавить сантехнику обработчика событий. Начните с добавления обработчика событий в класс кода программной части в protected
качестве метода следующим образом:
protected void RoleCheckBox_CheckChanged(object sender, EventArgs e)
{
}
Мы вернемся к написанию кода для этого обработчика событий через некоторое время. Но сначала давайте завершим обработку событий сантехники. Из checkBox в элементе Repeater добавьте ItemTemplate
OnCheckedChanged="RoleCheckBox_CheckChanged"
. Этот синтаксис подключает RoleCheckBox_CheckChanged
обработчик событий к событию RoleCheckBox
CheckedChanged
.
<asp:CheckBox runat="server" ID="RoleCheckBox"
AutoPostBack="true"
Text='<%# Container.DataItem %>'
OnCheckedChanged="RoleCheckBox_CheckChanged" />
Последняя задача — завершить RoleCheckBox_CheckChanged
обработчик событий. Для начала необходимо сослаться на элемент управления CheckBox, который вызвал событие, так как этот экземпляр CheckBox сообщает нам, какая роль была проверена или снята с помощью свойств Text
и Checked
. Используя эти сведения вместе с именем пользователя выбранного пользователя, мы добавляем или удаляем пользователя из роли с помощью Roles
метода или RemoveUserFromRole
класса AddUserToRole
.
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);
}
}
Приведенный выше код начинается с программной ссылки на элемент CheckBox, который вызвал событие, доступное через входной sender
параметр. Если флажок CheckBox установлен, выбранный пользователь добавляется в указанную роль, в противном случае он удаляется из роли. В любом случае в поле ActionStatus
Метка отображается сообщение, в котором приводится сводка только что выполненного действия.
Проверьте эту страницу в браузере. Выберите пользователя Tito, а затем добавьте Tito в роли Администраторы и Супервизоры.
Рис. 3. Тито добавлен в роли администраторов и руководителей (щелкните, чтобы просмотреть полноразмерное изображение)
Затем выберите пользователя Брюса из раскрывающегося списка. Существует обратная связь, и checkBox repeater обновляется с помощью CheckRolesForSelectedUser
. Так как Брюс еще не принадлежит ни к одной роли, два флажка сняты. Затем добавьте Брюса в роль "Супервизоры".
Рис. 4. Брюс добавлен в роль "Супервизоры" (щелкните для просмотра полноразмерного изображения)
Чтобы дополнительно проверить функциональность метода, выберите пользователя, отличного CheckRolesForSelectedUser
от Тито или Брюса. Обратите внимание, что флажки автоматически сняты, указывая, что они не принадлежат ни к одной роли. Вернитесь к Тито. Установите флажки Администраторы и Супервизоры.
Шаг 2. Создание пользовательского интерфейса "По ролям"
На этом этапе мы завершили работу с интерфейсом "по пользователям" и готовы приступить к работе с интерфейсом "по ролям". Интерфейс "по ролям" предлагает пользователю выбрать роль из раскрывающегося списка, а затем отображает набор пользователей, принадлежащих к этой роли, в GridView.
Добавьте на страницу UsersAndRoles.aspx
еще один элемент управления DropDownList. Поместите его под элементом управления Repeater, назовите его RoleList
и задайте для его AutoPostBack
свойства значение True. Под этим элементом добавьте GridView и назовите его RolesUserList
. Этот элемент GridView выводит список пользователей, принадлежащих к выбранной роли. Задайте для свойства GridView AutoGenerateColumns
значение False, добавьте TemplateField в коллекцию сетки Columns
и задайте для его HeaderText
свойства значение Users. Определите свойство TemplateField таким ItemTemplate
образом, чтобы оно отображало значение выражения Container.DataItem
привязки данных в Text
свойстве объекта Label с именем UserNameLabel
.
После добавления и настройки GridView декларативная разметка интерфейса "по роли" должна выглядеть примерно так:
<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>
Необходимо заполнить RoleList
DropDownList набором ролей в системе. Для этого обновите BindRolesToList
метод так, чтобы он привязал массив строк, возвращаемый методом Roles.GetAllRoles
, к RolesList
DropDownList (а также к UsersRoleList
repeater).
private void BindRolesToList()
{
// Get all of the roles
string[] roles = Roles.GetAllRoles();
UsersRoleList.DataSource = roles;
UsersRoleList.DataBind();
RoleList.DataSource = roles;
RoleList.DataBind();
}
Последние две строки в BindRolesToList
метод были добавлены для привязки набора ролей к элементу RoleList
управления DropDownList. На рисунке 5 показан конечный результат при просмотре через браузер — раскрывающийся список, заполненный ролями системы.
Рис. 5. Роли отображаются в RoleList
раскрывающемся списке (щелкните, чтобы просмотреть полноразмерное изображение)
Отображение пользователей, принадлежащих к выбранной роли
При первой загрузке страницы или при выборе новой роли в RoleList
Раскрывающемся списке необходимо отобразить список пользователей, принадлежащих этой роли, в GridView. Создайте метод с именем DisplayUsersBelongingToRole
, используя следующий код:
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();
}
Этот метод начинается с получения выбранной роли из RoleList
DropDownList. Затем он использует Roles.GetUsersInRole(roleName)
метод для получения массива строк UserNames пользователей, принадлежащих к этой роли. Затем этот массив привязывается к RolesUserList
GridView.
Этот метод необходимо вызывать в двух случаях: при первоначальной загрузке страницы и при изменении выбранной роли в Раскрывающемся RoleList
списке. Поэтому обновите Page_Load
обработчик событий так, чтобы этот метод вызывался после вызова CheckRolesForSelectedUser
метода . Затем создайте обработчик событий для RoleList
SelectedIndexChanged
события и вызовите этот метод.
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();
}
При использовании этого кода в RolesUserList
GridView должны отображаться пользователи, принадлежащие к выбранной роли. Как показано на рисунке 6, роль "Руководители" состоит из двух членов: Брюса и Тито.
Рис. 6. GridView выводит список пользователей, принадлежащих к выбранной роли (щелкните для просмотра полноразмерного изображения)
Удаление пользователей из выбранной роли
Давайте добавим RolesUserList
GridView, чтобы он был включен в столбец кнопок "Удалить". Нажатие кнопки "Удалить" для определенного пользователя приведет к удалению его из этой роли.
Начните с добавления поля кнопки Удалить в GridView. Сделайте это поле наиболее левым и измените его DeleteText
свойство с "Delete" (по умолчанию) на "Удалить".
Рис. 7. Добавление кнопки "Удалить" в GridView (щелкните для просмотра полноразмерного изображения)
При нажатии кнопки "Удалить" происходит обратная связь и возникает событие GridView RowDeleting
. Необходимо создать обработчик событий для этого события и написать код, который удаляет пользователя из выбранной роли. Создайте обработчик событий и добавьте следующий код:
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);
}
Код начинается с определения имени выбранной роли. Затем он программно ссылается на UserNameLabel
элемент управления из строки, для которой была нажата кнопка "Удалить", чтобы определить имя пользователя, удаляемого пользователя. Затем пользователь удаляется из роли с помощью вызова Roles.RemoveUserFromRole
метода . Затем RolesUserList
GridView обновляется, и сообщение отображается с помощью ActionStatus
элемента управления Метка.
Примечание
Кнопка "Удалить" не требует подтверждения от пользователя перед удалением пользователя из роли. Я приглашаю вас добавить некоторый уровень подтверждения пользователя. Одним из самых простых способов подтверждения действия является диалоговое окно подтверждения на стороне клиента. Дополнительные сведения об этом методе см. в разделе Добавление подтверждения Client-Side при удалении.
На рисунке 8 показана страница после удаления пользователя Tito из группы "Супервизоры".
Рис. 8. Увы, Тито больше не является руководителем (щелкните для просмотра полноразмерного изображения)
Добавление новых пользователей в выбранную роль
Наряду с удалением пользователей из выбранной роли посетитель этой страницы также должен иметь возможность добавить пользователя в выбранную роль. Оптимальный интерфейс для добавления пользователя к выбранной роли зависит от ожидаемого количества учетных записей пользователей. Если на вашем веб-сайте будет размещено всего несколько десятков учетных записей пользователей или меньше, вы можете использовать DropDownList здесь. Если могут быть тысячи учетных записей пользователей, необходимо включить пользовательский интерфейс, который позволяет посетителю просматривать страницы учетных записей, искать определенную учетную запись или фильтровать учетные записи пользователей другим способом.
Для этой страницы мы используем очень простой интерфейс, который работает независимо от количества учетных записей пользователей в системе. А именно, мы будем использовать элемент TextBox, предлагающий посетителю ввести имя пользователя, которого он хочет добавить в выбранную роль. Если нет пользователя с таким именем или пользователь уже является членом роли, мы выведем сообщение в ActionStatus
label. Но если пользователь существует и не является членом роли, мы добавим его в роль и обновим сетку.
Добавьте textBox и Button под GridView. Задайте для элемента TextBox ID
значение UserNameToAddToRole
, а свойства AddUserToRoleButton
и Button ID
Text
— значение и "Добавить пользователя в роль" соответственно.
<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>
Затем создайте Click
обработчик событий для AddUserToRoleButton
и добавьте следующий код:
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); }
Большая часть кода в обработчике Click
событий выполняет различные проверки. Это гарантирует, что посетитель предоставил имя пользователя в UserNameToAddToRole
TextBox, что пользователь существует в системе и что он еще не принадлежит к выбранной роли. Если какая-либо из этих проверок завершается сбоем, отображается ActionStatus
соответствующее сообщение и обработчик событий завершается. Если все проверки пройдены, пользователь добавляется в роль с помощью Roles.AddUserToRole
метода . После этого свойство TextBox Text
очищается, GridView обновляется, а в ActionStatus
поле Метка отображается сообщение о том, что указанный пользователь успешно добавлен в выбранную роль.
Примечание
Чтобы убедиться, что указанный пользователь еще не принадлежит выбранной роли, мы используем Roles.IsUserInRole(userName, roleName)
метод , который возвращает логическое значение, указывающее, является ли userName членом roleName. Мы снова будем использовать этот метод в следующем руководстве, когда мы рассмотрим авторизацию на основе ролей.
Перейдите на страницу в браузере и выберите роль "Руководители" в раскрывающемся RoleList
списке. Попробуйте ввести недопустимое имя пользователя. Вы увидите сообщение о том, что пользователь не существует в системе.
Рис. 9. Невозможно добавить несуществующего пользователя в роль (щелкните для просмотра полноразмерного изображения)
Теперь попробуйте добавить допустимого пользователя. Добавьте Тито в роль "Руководители".
Рис. 10. Тито снова руководитель! (Щелкните для просмотра полноразмерного изображения)
Шаг 3. Перекрестное обновление интерфейсов "По пользователю" и "По роли"
Страница UsersAndRoles.aspx
предлагает два различных интерфейса для управления пользователями и ролями. В настоящее время эти два интерфейса действуют независимо друг от друга, поэтому возможно, что изменения, внесенные в одном интерфейсе, не будут отражены сразу в другом. Например, представьте, что посетитель страницы выбирает роль "Руководители" в RoleList
раскрывающемся списке, в котором в качестве участников указаны Брюс и Тито. Затем посетитель выбирает Tito в UserList
раскрывающемся списке, который устанавливает флажки Администраторы и Руководители в ретрансляторе UsersRoleList
. Если посетитель снимет флажок "Супервайзер" в ретрансляторе, Тито удаляется из роли "Руководители", но это изменение не отражается в интерфейсе "по ролям". GridView по-прежнему будет отображать Тито как члена роли "Руководители".
Чтобы устранить эту проблему, необходимо обновлять GridView всякий раз, когда роль проверяется или снята с ретранслятора UsersRoleList
. Аналогичным образом необходимо обновлять repeater всякий раз, когда пользователь удаляется или добавляется к роли из интерфейса "по роли".
Repeater в интерфейсе "by user" обновляется путем вызова CheckRolesForSelectedUser
метода . Интерфейс "по роли" можно изменить в RolesUserList
обработчике RowDeleting
событий GridView и AddUserToRoleButton
обработчике Click
событий Button. Поэтому необходимо вызвать CheckRolesForSelectedUser
метод из каждого из этих методов.
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();
}
Аналогичным образом GridView в интерфейсе "по роли" обновляется путем вызова DisplayUsersBelongingToRole
метода , а интерфейс "по пользователю" изменяется с помощью обработчика RoleCheckBox_CheckChanged
событий. Поэтому необходимо вызвать DisplayUsersBelongingToRole
метод из этого обработчика событий.
protected void RoleCheckBox_CheckChanged(object sender, EventArgs e)
{
... Code removed for brevity...
// Refresh the "by role" interface
DisplayUsersBelongingToRole();
}
С этими незначительными изменениями кода интерфейсы "по пользователю" и "по роли" теперь правильно перекрестно обновляются. Чтобы проверить это, перейдите на страницу в браузере и выберите Tito и Супервизоры в UserList
раскрывающихся списках и RoleList
соответственно. Обратите внимание, что при снятии флажка Роли "Руководители" для Tito в ретрансляторе в интерфейсе "по пользователю" Tito автоматически удаляется из GridView в интерфейсе "по роли". При добавлении Тито обратно в роль "Руководители" из интерфейса "по роли" автоматически проверяется флажок "Руководители" в интерфейсе "по пользователю".
Шаг 4. Настройка шага CreateUserWizard для включения шага "Указание ролей"
В учебнике Создание учетных записей пользователей мы узнали, как использовать веб-элемент управления CreateUserWizard для предоставления интерфейса для создания новой учетной записи пользователя. Элемент управления CreateUserWizard можно использовать одним из двух способов:
- В качестве средства для посетителей, чтобы создать собственную учетную запись пользователя на сайте, и
- Как средство для создания новых учетных записей администраторами
В первом случае использования посетитель приходит на сайт и заполняет CreateUserWizard, вводя свои данные для регистрации на сайте. Во втором случае администратор создает новую учетную запись для другого пользователя.
Если учетная запись создается администратором для другого пользователя, может быть полезно разрешить администратору указать, к каким ролям принадлежит новая учетная запись пользователя. В руководстве По хранению дополнительных сведений о пользователе мы узнали, как настроить CreateUserWizard путем добавления дополнительных сведений WizardSteps
. Давайте рассмотрим, как добавить дополнительный шаг в CreateUserWizard, чтобы указать роли нового пользователя.
Откройте страницу CreateUserWizardWithRoles.aspx
и добавьте элемент управления CreateUserWizard с именем RegisterUserWithRoles
. Задайте для свойства элемента управления ContinueDestinationPageUrl
значение "~/Default.aspx". Так как идея заключается в том, что администратор будет использовать этот элемент управления CreateUserWizard для создания новых учетных записей пользователей, присвойте LoginCreatedUser
свойству элемента управления значение False. Это LoginCreatedUser
свойство указывает, будет ли посетитель автоматически входить в систему как только что созданный пользователь, и по умолчанию используется значение True. Мы устанавливаем для него значение False, так как когда администратор создает новую учетную запись, мы хотим, чтобы он вошел в систему как сам.
Затем выберите "Добавить или удалить WizardSteps
..." параметр из смарт-тега CreateUserWizard и добавьте новый WizardStep
, задав для нее ID
значение SpecifyRolesStep
. SpecifyRolesStep WizardStep
Переместите , чтобы он был выполнен после шага "Регистрация для новой учетной записи", но до шага "Завершить". Присвойте Title
свойству WizardStep
значение "Указать роли", свойству StepType
Step
— значение , а свойству AllowReturn
— значение False.
Рис. 11. Добавление элемента "Укажите роли" WizardStep
в createUserWizard (щелкните для просмотра полноразмерного изображения)
После этого изменения декларативная разметка CreateUserWizard должна выглядеть следующим образом:
<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>
В разделе "Укажите роли" WizardStep
добавьте элемент CheckBoxList с именем RoleList
. Этот элемент CheckBoxList выводит список доступных ролей, позволяя пользователю, посещающему страницу, проверка, к каким ролям принадлежит только что созданный пользователь.
Осталось выполнить две задачи программирования: во-первых, необходимо заполнить RoleList
CheckBoxList ролями в системе; во-вторых, необходимо добавить созданного пользователя к выбранным ролям при переходе пользователя с шага "Указание ролей" на шаг "Завершить". Мы можем выполнить первую задачу в обработчике Page_Load
событий. Следующий код программно ссылается RoleList
на Элемент CheckBox при первом посещении страницы и привязывает к нему роли в системе.
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();
}
}
Приведенный выше код должен выглядеть знакомо. В учебнике Хранениедополнительных сведений о пользователе мы использовали два FindControl
оператора для ссылки на веб-элемент управления из пользовательского WizardStep
. Код, который привязывает роли к CheckBoxList, был взят ранее в этом руководстве.
Чтобы выполнить вторую задачу программирования, необходимо знать, когда был завершен шаг "Указание ролей". Помните, что createUserWizard имеет ActiveStepChanged
событие, которое срабатывает каждый раз, когда посетитель переходит с одного шага на другой. Здесь можно определить, достиг ли пользователь шага "Завершить"; Если да, необходимо добавить пользователя к выбранным ролям.
Создайте обработчик событий для ActiveStepChanged
события и добавьте следующий код:
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);
}
}
}
Если пользователь только что достиг шага "Завершено", обработчик событий перечисляет элементы RoleList
CheckBoxList и только что созданному пользователю назначается выбранные роли.
Посетите эту страницу в браузере. Первым шагом в CreateUserWizard является стандартный шаг "Регистрация для новой учетной записи", который запрашивает имя пользователя, пароль, адрес электронной почты и другие ключевые сведения нового пользователя. Введите сведения для создания нового пользователя С именем Wanda.
Рис. 12. Создание пользователя с именем Wanda (щелкните, чтобы просмотреть изображение в полном размере)
Нажмите кнопку "Создать пользователя". CreateUserWizard внутренне вызывает Membership.CreateUser
метод , создавая новую учетную запись пользователя, а затем переходит к следующему шагу , "Укажите роли". Здесь перечислены системные роли. Установите флажок Руководители и нажмите кнопку Далее.
Рис. 13. Назначение Wanda членом роли "Руководители" (щелкните для просмотра полноразмерного изображения)
При нажатии кнопки Далее происходит обратная связь и выполняется обновление ActiveStep
до шага "Завершить". В обработчике ActiveStepChanged
событий недавно созданной учетной записи пользователя назначается роль "Руководители". Чтобы убедиться в этом, вернитесь на страницу UsersAndRoles.aspx
и выберите "Супервизоры" в RoleList
раскрывающемся списке. Как показано на рисунке 14, руководители теперь состоят из трех пользователей: Брюса, Тито и Ванда.
Рис. 14. Брюс, Тито и Ванда — все руководители (щелкните для просмотра полноразмерного изображения)
Сводка
Платформа ролей предлагает методы для получения сведений о ролях конкретного пользователя и методы определения того, какие пользователи принадлежат указанной роли. Кроме того, существует ряд методов добавления и удаления одного или нескольких пользователей в одну или несколько ролей. В этом руководстве мы сосредоточились только на двух из этих методов: AddUserToRole
и RemoveUserFromRole
. Существуют дополнительные варианты, предназначенные для добавления нескольких пользователей к одной роли и назначения нескольких ролей одному пользователю.
В этом руководстве также рассматривается расширение элемента управления CreateUserWizard, чтобы включить для WizardStep
указания ролей только что созданных пользователей. Такой шаг поможет администратору упростить процесс создания учетных записей пользователей для новых пользователей.
На этом этапе мы видели, как создавать и удалять роли, а также как добавлять и удалять пользователей из ролей. Но нам еще предстоит рассмотреть применение авторизации на основе ролей. В следующем руководстве мы рассмотрим определение правил авторизации URL-адресов на основе ролей по ролям, а также об ограничении функциональных возможностей на уровне страницы на основе ролей вошедшего в систему пользователя.
Счастливого программирования!
Дополнительные материалы
Дополнительные сведения о темах, рассмотренных в этом руководстве, см. в следующих ресурсах:
- Общие сведения о средстве администрирования веб-сайтов ASP.NET
- Изучение ASP. Членство, роли и профиль NET
Об авторе
Скотт Митчелл (Scott Mitchell), автор нескольких книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 2.0 в 24 часа. Скотт можно связаться по адресу mitchell@4guysfromrolla.com или через его блог по адресу http://ScottOnWriting.NET.
Отдельная благодарность...
Эта серия учебников была проверена многими полезными рецензентами. Ведущим рецензентом этого руководства была Тереса Мерфи. Хотите ознакомиться с моими предстоящими статьями MSDN? Если да, бросить мне линию на mitchell@4GuysFromRolla.com