Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7
Для работы с ролями ASP.NET Core Identity предоставляет класс IdentityRole. В этом классе определяется несколько свойств:
public virtual TKey Id { get; set; } public virtual string Name { get; set; } public virtual string NormalizedName { get; set; } public virtual string ConcurrencyStamp { get; set; }
Основым является свойство Name, которое и хранит название роли.
Возьмем какой-нибудь имеющийся контроллер и применим к нему доступ по ролям. Например:
using Microsoft.AspNetCore.Authorization; [Authorize(Roles="admin")] public class HomeController : Controller { // содержимое контроллера }
В данном случае мы указали, что доступ к контроллеру HomeController будет открыт только для пользователей, которые принадлежат к роли "admin". Но на данный момент у нас нет никакой роли "admin".
Рассмотрим как мы можем управлять ролями и для это продолжим работу с проектом из прошлой темы (либо создадим новый проект с ASP.NET Core Identity). Для администрирования ролями воспользуемся методами классов UserManager и RoleManager.
Вначале добавим в папку ViewModels модель ChangeRoleViewModel:
using Microsoft.AspNetCore.Identity; using System.Collections.Generic; public class ChangeRoleViewModel { public string UserId { get; set; } public string UserEmail { get; set; } public List<IdentityRole> AllRoles { get; set; } public IList<string> UserRoles { get; set; } public ChangeRoleViewModel() { AllRoles = new List<IdentityRole>(); UserRoles = new List<string>(); } }
Эта модель позволит управлять всеми ролями для одного пользователя (в ASP.NET Core Identity один пользователь може иметь множество ролей).
Вначале добавим в папку Controllers новый контроллер RolesController:
using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using CustomIdentityApp.Models; using CustomIdentityApp.ViewModels; namespace CustomIdentityApp.Controllers { public class RolesController : Controller { RoleManager<IdentityRole> _roleManager; UserManager<User> _userManager; public RolesController(RoleManager<IdentityRole> roleManager, UserManager<User> userManager) { _roleManager = roleManager; _userManager = userManager; } public IActionResult Index() => View(_roleManager.Roles.ToList()); public IActionResult Create() => View(); [HttpPost] public async Task<IActionResult> Create(string name) { if (!string.IsNullOrEmpty(name)) { IdentityResult result = await _roleManager.CreateAsync(new IdentityRole(name)); if (result.Succeeded) { return RedirectToAction("Index"); } else { foreach (var error in result.Errors) { ModelState.AddModelError(string.Empty, error.Description); } } } return View(name); } [HttpPost] public async Task<IActionResult> Delete(string id) { IdentityRole role = await _roleManager.FindByIdAsync(id); if (role != null) { IdentityResult result = await _roleManager.DeleteAsync(role); } return RedirectToAction("Index"); } public IActionResult UserList() => View(_userManager.Users.ToList()); public async Task<IActionResult> Edit(string userId) { // получаем пользователя User user = await _userManager.FindByIdAsync(userId); if(user!=null) { // получем список ролей пользователя var userRoles = await _userManager.GetRolesAsync(user); var allRoles = _roleManager.Roles.ToList(); ChangeRoleViewModel model = new ChangeRoleViewModel { UserId = user.Id, UserEmail = user.Email, UserRoles = userRoles, AllRoles = allRoles }; return View(model); } return NotFound(); } [HttpPost] public async Task<IActionResult> Edit(string userId, List<string> roles) { // получаем пользователя User user = await _userManager.FindByIdAsync(userId); if(user!=null) { // получем список ролей пользователя var userRoles = await _userManager.GetRolesAsync(user); // получаем все роли var allRoles = _roleManager.Roles.ToList(); // получаем список ролей, которые были добавлены var addedRoles = roles.Except(userRoles); // получаем роли, которые были удалены var removedRoles = userRoles.Except(roles); await _userManager.AddToRolesAsync(user, addedRoles); await _userManager.RemoveFromRolesAsync(user, removedRoles); return RedirectToAction("UserList"); } return NotFound(); } } }
В контроллере получаем объекты RoleManager и UserManager, которые передаются через механизм внедрения зависимостей.
Для представлений для данного контроллера сразу определим в папке Views каталог Roles.
Метод Index выводит список ролей. Для их вывода добавим в каталог Views/Roles новое представление Index.cshtml:
@model IEnumerable<Microsoft.AspNetCore.Identity.IdentityRole> <h2>Список ролей</h2> <table class="table"> @foreach (var role in Model) { <tr> <td>@role.Name</td> <td> <form asp-action="Delete" asp-route-id="@role.Id" method="post"> <button type="submit" class="btn btn-sm btn-danger"> Удалить </button> </form> </td> </tr> } </table> <a asp-action="Create">Добавить роль</a> <a asp-action="UserList">Список пользователей</a>
В методе Create создаем роль и добавляем ее через вызов _roleManager.CreateAsync()
. Также добавим для этого метода представление
Create.cshtml:
@model string <div asp-validation-summary="All" class="text-danger"></div> <form asp-action="Create" method="post"> <div class="form-group"> <label for="name">Новая роль</label> <input name="name" class="form-control" /> </div> <button type="submit" class="btn btn-primary">Добавить</button> </form>
В методе Delete по id получаем роль и удаляем ее с помощью вызова метода _roleManager.DeleteAsync()
.
Отдельно стоит сказать про редактирование. Поскольку класс IdentityRole содержит только два свойства: Id и Name, то особо редактировать здесь нечего. Можно конечно изменять значение свойства Name, но это нежелательно, поскольку в приложении могут использоваться атрибуты Authorize, которые по имени роли устанавливают ограничение доступа. Но, конечно, если бы роль представляла какой-то производный класс от IdentityRole и имела бы какие-то дополнительные свойства, то там было бы больше возможностей по редактированию.
В данном же случае для примера используется редактирование списка ролей, к которым принадлежит определенный пользователь. Для вывода списка пользователей здесь определен метод UserList. Для вывода пользователей добавим следующее представление UserList.cshtml:
@model IEnumerable<CustomIdentityApp.Models.User> <h2>Список пользователей</h2> <table class="table"> @foreach (var user in Model) { <tr> <td>@user.Email</td> <td> <a class="btn btn-sm btn-primary" asp-action="Edit" asp-route-userid="@user.Id">Права доступа</a> </td> </tr> } </table>
По нажатию на ссылку в этом представлении в метод Edit передается id пользователя. Затем из этого метод в представление через специальную модель ChangeRoleViewModel передаются его id, email, роли, а также список вообще всех ролей из базы данных.
И также добавим для этого метода в папку Views/Roles представление Edit.cshtml:
@using Microsoft.AspNetCore.Identity @model CustomIdentityApp.ViewModels.ChangeRoleViewModel <h2>Изменение ролей для пользователя @Model.UserEmail</h2> <form asp-action="Edit" method="post"> <input type="hidden" name="userId" value="@Model.UserId" /> <div class="form-group"> @foreach (IdentityRole role in Model.AllRoles) { <input type="checkbox" name="roles" value="@role.Name" @(Model.UserRoles.Contains(role.Name) ? "checked=\"checked\"" : "") />@role.Name <br /> } </div> <button type="submit" class="btn btn-primary">Сохранить</button> </form>
С помощью флажков (<input type="checkbox" >
) здесь выводятся все роли. А те роли, для которых добавлен данный пользователь, имеют
отмеченные флажки.
В post-версии действия Edit мы ожидаем получить id редактируемого пользователя и список выбранных ролей. С помощью операции разности множеств получаем добавленные
и удаленные роли и далее применяем к ним методы _userManager.AddToRolesAsync()
и _userManager.RemoveFromRolesAsync()
.
Основные моменты, добавленные в этой теме в проект:
Добавим несколько ролей и перейдем к методу Index:
Перейдем к списку пользователей:
И изменим для кого-нибудь из них набор ролей: