Авторизация в приложении Blazor Server

Все исходники /  Язык программирования C# /  OS Windows /  Web ASP.NET /  Blazor / Авторизация в приложении Blazor Server

Авторизированный доступ

На основе панели администратора описанной в статье Blazor админ панель создана версия админ панели с авторизацией входа. Ниженаписанное касается только версии приложения Bazor Server.

Сценарии безопасности для приложений Blazor Server и Blazor WebAssembly отличаются. Так как приложения Blazor Server выполняются на стороне сервера, проверки авторизации могут определить следующее: параметры пользовательского интерфейса, предоставленные пользователю (например, какие пункты меню доступны пользователю); правила доступа для приложений и компонентов.

Приложения Blazor WebAssembly выполняются на стороне клиента. В этом случае авторизация используется только для определения отображаемых вариантов пользовательского интерфейса. Так как пользователь может изменить или обойти проверки на стороне клиента, приложение Blazor WebAssembly не может применять правила авторизации доступа.

Авторы: Стив Сандерсон (Steve Sanderson) и Люк Лэтем (Luke Latham) ASP.NET Core Blazor authentication and authorization

Шаблон с аутентификацией

Структура папок с аутентификацией

Создадим предварительный шаблон с аутентификацией пользователей для административной панели. Для этого в MS Visual Studio 2019 запустим создание приложения Blazor Server, установим версию .NET Core 3.1. В настройках аутентификации изменим способ проверки подлинности на учетные записи отдельных пользователей.

Заметьте, что приложение создаётся c HTTPS поскольку других средств шифрования конфиденциальных данных у приложения нет. Если не использовать протокол HTTPS данные в сеть будут уходить в открытом виде. Протокол HTTPS избавляет программиста от трудоемкой работы по созданию безопасного кода на основе HTTP и javascript.

Формируем структуру папок для закрытой админ панели в области Areas. Создаём папку AdminPanel, в ней создаём две папки Pages и Shared для компонентов админпанели.

Удаляем файлы стандартного шаблона. В папке Pages оставляем только файлы _Host.cshtml из Error.cshtml. Из корневой папки Shared переносим файлы MainLayout.razor, LoginDisplay.razor и NavMenu.razor в папку /Areas/AdminPanel/Shared/, остальные файлы можно удалить. Для того чтобы в файле App.razor не нарушилась маршрутизация после переноса главного макета в корневой файл _Imports.razor необходимо добавить директиву нового пути к макету @using BSAdminPanel.Areas.AdminPanel.Shared

На рисунке показана структура папок предварительного каркаса для админ панели с авторизацией.

Перенос компонентов админпанели

Структура папок админ панели с авторизацией

Теперь необходимо перенести компоненты, папки моделей и баз данных, папки стилей и javascript из проекта админ панели описанной в статье Blazor админ панель.

В папке AdminPanel создадим файл импорта _Imports.razor для подключения необходимых пространств имен и путей доступа к общим компонентам и моделям. Компилятор включит директивы, указанные в файле импорта, во все компоненты папки AdminPanel и рекурсивно во всех ее вложенных папках.

В итоге, после переноса и корректировки должна сформироваться структура как показано на изображении. После запуска приложения, на данном этапе, панель администратора должна функционировать в свободном доступе, не требуя авторизацию.

Листинг файла импорта папки AdmniPanel:
@using Microsoft.JSInterop
@using BSAdminPanel.Areas.AdminPanel.Shared
@using BSAdminPanel.Areas.AdminPanel.Shared.MyComponents
@using BSAdminPanel.Models

Аутентификация при входе

После проверки работы приложения, приступаем к организации проверки подлинности пользователей при входе в панель управления. В файл /Areas/AdminPanel/_Imports.razor добавим @attribute [Authorize] для запрета доступа к страницам папки без идентификации пользователя. Теперь при запуске приложения формируется страница с интерфейсом доступа и навигационным меню панели управления, но вместо содержания служебная надпись «Not authorized». В приложении ещё нет механизма, отсеивающего не авторизированный доступ к закрытым веб страницам.

По умолчанию файл App.razor, входной компонент приложения ответственный за маршрутизацию, не имеет компонента предназначенного для обработки неавторизированного доступа. Запрет к закрытым страницам с атрибутом Authorize стандартно осуществляет добавленный при создании приложения встроенный пользовательский интерфейс Microsoft.AspNetCore.Identity.UI.

Листинг файла App.razor созданный MS Visual Studio для шаблона приложения Blazor Server:
<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(Program).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
        </AuthorizeRouteView>
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>
Для подключения своего компонента обрабатывающего попытку неавторизованного доступа в App.razor добавим теги:
<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(Program).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <!-- -->
                <NotAuthorized>
                    Вход воспрещён!
                </NotAuthorized>
                <!-- -->
        </AuthorizeRouteView>
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

Теперь при запуске приложения будет выходить надпись “Вход воспрещен”. Но главная страница сайта всё равно создаётся на основе файла _Host.cshtml с навигационным администраторским меню, со всеми его файлами css и javascript функциями. Теперь необходимо создать компонент, который будет автоматически перенаправлять неавторизированных пользователей на страницу логинирования или аутентификации, без участия главного файла панели администратора _Host.cshtml.

Компонент для обработки попыток входа неавторизированных пользователей может иметь любое имя. Назовём его NotAuthorizedHandler.razor и добавим в него поддержку класса NavigationManager, служащий для управления URI навигацией. Код перенаправления разместим в теле самого первого метода жизненного цикла компонента Blazor Server SetParametersAsync(…). Расположим этот компонент в корневой папке Shared.

Листинг кода компонента NotAuthorizedHandler.razor
@inject NavigationManager navigation

@code {

    public override async Task SetParametersAsync(ParameterView parameters)
    {
        navigation.NavigateTo("/Identity/Account/Login");

        await base.SetParametersAsync(parameters);
    }
}

Теперь при загрузке приложения будет появляться специальная страница аутентификации. Для входа в авторизированную зону необходимо зарегистрироваться и затем успешно работать в панели администратора. Для тестирования регистраций и авторизаций можно понизить уровень строгости проверки пароля. Для этого в файле Startup.cs, в методе ConfigureServices(IServiceCollection services) изменить опции идентификации.

Код изменения стандартных опций идентификации:
// Отключаем стандартную идентификацию.
//services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true)

// Понижаем строгость проверки пароля.
services.AddDefaultIdentity(options =>
    {
        options.SignIn.RequireConfirmedAccount = false;
        options.Password.RequiredLength = 6;
        options.Password.RequiredUniqueChars = 0;
        options.Password.RequireLowercase = false;
        options.Password.RequireUppercase = false;
        options.Password.RequireNonAlphanumeric = false;
    }
).AddEntityFrameworkStores();

При первой регистрации на сайте выйдет страница с такой ошибкой:
A database operation failed while proccesing the request
Applying existing migrations for ApplicationDbContext may resolve this issue
( Ошибка операции с базой данных при обработке запроса
Принятие существующую миграцию для ApplicationDbContext может решить эту проблему.)

Это означает что база данных еще не создана, необходимо нажать на кнопку Apply Migrations и запустить процесс создания базы данных для возможности регистрации пользователей. Затем обновить страницу и, если регистрация была успешной, откроется администраторская панель управления. Создание приложения Blazor Server с авторизацией функционально готово.

Безопасность панели админа

Хотя функциональность приложения с авторизацией готова. Есть еще некоторые вопросы, которые не разрешают использовать данное веб приложение в качестве администраторской панели:
  • Не допускается произвольная регистрация пользователей для панели админа, только администраторы сайта должны иметь доступ к интерфейсу регистрации. Поэтому регистрацию необходимо перенести в зону закрытого доступа, иначе теряется смысл идентификации пользователей для панели администратора.
  • Создание собственных страниц авторизации, с требуемой языковой локализацией.

Безопасность панели администратора подразумевает только начальную страницу аутентификации, нет других страниц, т. е. регистраций, изменения паролей и т. д. Это всё должно происходить уже в зоне администрирования после авторизации. Создание паролей и логинов для пользователей осуществляет администратор.

Добавление Scaffold Identity

Добавим код страниц регистрации и логинирования в наше приложение. Для этого воспользуемся шаблоном Scaffold Identity, для выборочного добавления исходного кода, содержащегося в Identity Razor библиотеке классов (RCL).

  • Правой кнопкой мыши щелкнуть на название проекта (в нашем случае BSAdminPanel).
  • В контекстном меню выбрать Добавить->Создать шаблонный элемент.
  • В диалоговом окне, слева, выбрать Удостоверение
  • В диалоге Добавить Удостоверение отмечаем два файла для переопределения: Account\Login и Account\Register
  • Класс контекста данных выбрать который уже есть в приложении
  • Выбор страницы макета оставьте нетронутым. Макет сформируется автоматически.
Добавление Scaffold Identity

После cформирования всей структуры папок в приложении два файла _LoginPartial.cshtml. Структура формируется на новый файл, который находится в папке «/Pages/Shared/_LoginPartial.cshtml», его оставляем. А в папке «/Areas/Identity/Pages/Shared/_LoginPartial.cshtml» можно удалить. Структура строится по типу шаблона для Razor Pages.

Регистрация после авторизации

Интерфейс регистрации сделаем доступным только после входа в панель управления. Для этого, в файле /Areas/Identity/Pages/Account/Register.cshtml.cs изменим атрибут доступа:
// Анонимный доступ удаляем
//[AllowAnonymous]

// Авторизированный добавляем.
[Authorize]
public class RegisterModel : PageModel
{
	...

	public RegisterModel(
		UserManager userManager,
		SignInManager signInManager,
		ILogger logger,
		IEmailSender emailSender)
	{
		_userManager = userManager;
		_signInManager = signInManager;
		_logger = logger;
		_emailSender = emailSender;
	}
}

Изменяем файл /Pages/Shared/_LoginPartial.cshtml – удаляем из меню ссылку на регистрацию. В файле /Areas/AdminPanel/Shared/LoginDisplay.razor также делаем изменения интерфейса. Из меню открытого доступа удаляем ссылку на регистрацию и переносим ее в доступ с авторизацией.

<AuthorizeView>
    <Authorized>
        <a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a>
         @* Сюда вставляем ссылку на страницу регистрации *@
        <a href="Identity/Account/Register">Register</a>
        <form method="post" action="Identity/Account/LogOut">
            <button type="submit" class="nav-link btn btn-link">Log out</button>
        </form>
    </Authorized>
    <NotAuthorized>
        @* Здесь удаляем и переносим в авторизированную зону*@
        @*<a href="Identity/Account/Register">Register</a>*@
        <a href="Identity/Account/Login">Log in</a>
    </NotAuthorized>
</AuthorizeView>

Итог

Вот теперь всё готово. Осталось только оформить по своему усмотрению файлы идентификации и панель администратора готова.

К статье прикреплён исходник панели администратора с авторизацией. Перед работой с исходным кодом приложения рекомендуется прочитать данную статью.

Скачать исходник