Blazor Server Authorization
Привіт!
Сьогодні подивимось, як додати авторизацію в Blazor Server. Для початку створимо новий проект, в якому включемо автентифікацію.
В проекті з автентифікацією присутні декілька додаткових файлів, які відповідають за автентифікацію. Також в конфігураційному файлі буде додано connection string до бази даних.
"ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-BlazorAuth-BD4B8646-B1A3-438C-8FFC-8C3A29438C24;Trusted_Connection=True;MultipleActiveResultSets=true" },
В package management консолі потрібно запустити команду Update-Database
для того, щоб створити базу даних та потрібні таблиці.
Тепер можна запустити аплікацію і спробувати залогуватись.
Тепер можна додати ролі для того, щоб обмежувати доступ до певних сторінок в залежності від ролі.
Autorization/h2>
Підтримку ролей потрібно добавити в Startup.cs
в методі ConfigureService
.
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddRoles<IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>();
Generate Roles
Додам новий razor-компонент в папку Pages
. При переході на цю сторінку будуть створюватись базові ролі, вона буде доступна за шляхом /addroles
. Також потрібно за допомогою DI взяти декілька об’єктів.
@page "/addroles" @using Microsoft.AspNetCore.Identity @inject RoleManager<IdentityRole> RoleManager @inject UserManager<IdentityUser> UserManager
Створювати ролі буду за допомогою RoleManager
. Для початку створю список, в якому будуть всі потрібні ролі. Далі іду циклом по усіх ролях, якщо роль існує, то нічого не відбудеться. Якщо ж ні, то нова роль буде створена.
private async Task GenerateRoles() { const string adminRole = "Administrator"; string[] roles = { AdminRole }; foreach (var role in roles) { var roleExist = await RoleManager.RoleExistsAsync(role); if (roleExist == false) { await RoleManager.CreateAsync(new IdentityRole(role)); } } }
Create admin
Наступним кроком потрібно додати користувачів до ролей. В appsettings.json
я додам параметр, який буде містити email дефолтного адміна.
"AdminUser": "[email protected]"
Повернусь назад до addroles
сторінки і створю новий метод. Перевіряю, чи користувач з емейлом з конфігураційного файлу існує, якщо так, то додаю його в групу Administrator
. Для того, щоб можна було прочитати дані з конфігураційного файлу, потрібо отримати об’єкт типу IConfiguration
. Вверху сторінки добавити @using Microsoft.Extensions.Configuration
i @inject IConfiguration config
.
private async Task AddAdmin() { var user = await UserManager.FindByEmailAsync(config.GetValue<string>("AdminUser")); if (user != null) { await UserManager.AddToRoleAsync(user, "Administrator"); } }
Для того, щоб ці методи викликались при відкритті сторінки, потрібно викликати їх в методі OnParametersSetAsync
.
Повний код addroles
сторінки
@page "/addroles" @using Microsoft.AspNetCore.Identity @using Microsoft.Extensions.Configuration @inject RoleManager<IdentityRole> RoleManager @inject UserManager<IdentityUser> UserManager @inject IConfiguration config @code { protected override async Task OnParametersSetAsync() { await GenerateRoles(); await AddAdmin(); } private async Task GenerateRoles() { const string adminRole = "Administrator"; string[] roles = { adminRole }; foreach (var role in roles) { var roleExist = await RoleManager.RoleExistsAsync(role); if (roleExist == false) { await RoleManager.CreateAsync(new IdentityRole(role)); } } } private async Task AddAdmin() { var user = await UserManager.FindByEmailAsync(config.GetValue<string>("AdminUser")); if (user != null) { await UserManager.AddToRoleAsync(user, "Administrator"); } } }
Тепер, відкривши в браузері сторінку /addroles
, роль буде створена та користувач (якщо існує) буде доданий в неї.
Restrict access to pages
Тепер коли в нас є ролі, можна обмежити доступ до сторінок. Для сторінки FetchData
я додам @attribute [Authorize]
. Це дасть доступ до сторінки тільки авторизованим користувачам. А для сторінки Counter
я вкажу @attribute [Authorize(Roles = "Administrator")]
це дасть доступ до сторінки тільки користувачам з ролю адміністратор.
Замінити Not Autorized помилку можна в App.razor
в NotAutorized
секції.
<CascadingAuthenticationState> <Router AppAssembly="@typeof(Program).Assembly"> <Found Context="routeData"> <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"> <NotAuthorized> <h1>You don't have access</h1> <p>Ask your administrator to give you permission</p> </NotAuthorized> </AuthorizeRouteView> /> </Found> <NotFound> <LayoutView Layout="@typeof(MainLayout)"> <p>Sorry, there's nothing at this address.</p> </LayoutView> </NotFound> </Router> </CascadingAuthenticationState>
Також можна повністю сховати елемент сайту для незареєстрованих користувачів. В NavMenu.razor
, я додам елементи меню в <AuthorizeView></AuthorizeView>
.
<div class="top-row pl-4 navbar navbar-dark"> <a class="navbar-brand" href="">BlazorAuth</a> <button class="navbar-toggler" @onclick="ToggleNavMenu"> <span class="navbar-toggler-icon"></span> </button> </div> <div class="@NavMenuCssClass" @onclick="ToggleNavMenu"> <ul class="nav flex-column"> <li class="nav-item px-3"> <NavLink class="nav-link" href="" Match="NavLinkMatch.All"> <span class="oi oi-home" aria-hidden="true"></span> Home </NavLink> </li> <AuthorizeView Roles="Administrator"> <li class="nav-item px-3"> <NavLink class="nav-link" href="counter"> <span class="oi oi-plus" aria-hidden="true"></span> Counter </NavLink> </li> </AuthorizeView> <AuthorizeView> <li class="nav-item px-3"> <NavLink class="nav-link" href="fetchdata"> <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data </NavLink> </li> </AuthorizeView> </ul> </div> @code { private bool collapseNavMenu = true; private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; private void ToggleNavMenu() { collapseNavMenu = !collapseNavMenu; } }
Тепер counter
в меню будуть бачити тільки користувачі з ролю Administrator
, а fetchdata
буде доступна зареєстрованим користувачам.
В index
сторінку додам повідомлення користувачам, щоб залогувались.
@page "/" <AuthorizeView> <Authorized> <h1>Thank you for logging in</h1> </Authorized> <NotAuthorized> <h3 class="text-danger">Log in please</h3> </NotAuthorized> </AuthorizeView> <AuthorizeView Roles="Administrator"> <Authorized> Welcome back Admin </Authorized> </AuthorizeView>
Якщо користувача не залоговний, буде повідомлення Log in please
. В інакшому випадку Thank you for logging in
. А якщо користувач admin, то додатково буде повідомлення Welcome back Admin
.
3 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів