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 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів