Проверка подлинности и авторизация в ASP.NET Core Blazor

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 9 этой статьи.

Предупреждение

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в статье о политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 8 этой статьи.

Внимание

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

В текущем выпуске см . версию .NET 9 этой статьи.

В этой статье приводятся сведения о поддержке настройки и администрирования функций безопасности в ASP.NET Core для приложений Blazor.

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

Если принудительное применение правил авторизации должно быть гарантировано, не реализуйте проверки авторизации в клиентском коде. Создайте сборку Blazor Web App , которая зависит только от отрисовки на стороне сервера (SSR) для проверок авторизации и применения правил.

Соглашения об авторизации Razor Pages не применяются к маршрутизируемым компонентам Razor. Если компонент, отличный от routableRazor, внедрен в страницу Razor приложения Pages, соглашения авторизации страницы косвенно влияют на Razor компонент вместе с rest содержимым страницы.

Если принудительное применение правил авторизации и безопасность данных и кода должны быть гарантированы, не разрабатывайте клиентское приложение. Blazor Server Создание приложения.

Соглашения об авторизации Razor Pages не применяются к маршрутизируемым компонентам Razor. Если компонент, отличный от routableRazor, внедрен в страницу Razor приложения Pages, соглашения авторизации страницы косвенно влияют на Razor компонент вместе с rest содержимым страницы.

ASP.NET Core Identity предназначен для работы в контексте связи HTTP-запроса и ответа, который обычно не является моделью взаимодействия с клиентом-сервером Blazor приложения. В приложениях ASP.NET Core, применяющих ASP.NET Core Identity для управления пользователями, следует использовать Razor Pages вместо компонентов Razor для пользовательского интерфейса, связанного с Identity, например для регистрации пользователей, входа, выхода и других задач управления пользователями. Сборка Razor компонентов, которые напрямую обрабатывают Identity задачи, возможна для нескольких сценариев, но не рекомендуется или поддерживается корпорацией Майкрософт.

Абстракции ASP.NET Core, например SignInManager<TUser> и UserManager<TUser>, не поддерживаются в компонентах Razor. Дополнительные сведения об использовании ASP.NET Core Identity с Blazorпомощью шаблонов ASP.NET Core Identity см. в серверном Blazor приложении.

Примечание.

Примеры кода в этой статье используют типы ссылок, допускающие значение NULL (NRTs) и статический анализ состояния .NET компилятора NULL, которые поддерживаются в ASP.NET Core в .NET 6 или более поздней версии. При назначении ASP.NET Core 5.0 или более ранней версии удалите обозначение типа NULL (?) из примеров в этой статье.

Безопасное обслуживание конфиденциальных данных и учетных данных

Не сохраняйте секреты приложений, строка подключения, учетные данные, пароли, персональные идентификационные номера (ПИН-коды), частный код .NET/C# или закрытые ключи и маркеры в клиентском коде, который всегда небезопасн. Клиентский Blazor код должен получить доступ к защищенным службам и базам данных через защищенный веб-API, который вы управляете.

В средах тестирования и промежуточной и рабочей среды код на стороне Blazor сервера и веб-API должны использовать безопасные потоки проверки подлинности, которые не поддерживают учетные данные в файлах кода проекта или конфигурации. Вне локального тестирования разработки рекомендуется избегать использования переменных среды для хранения конфиденциальных данных, так как переменные среды не являются наиболее безопасным подходом. Для локального тестирования разработки средство Secret Manager рекомендуется для защиты конфиденциальных данных. Дополнительные сведения см. на следующих ресурсах:

Для локальной разработки и тестирования на стороне клиента и сервера используйте средство Диспетчера секретов для защиты конфиденциальных учетных данных.

Управляемые удостоверения для служб Microsoft Azure

Для служб Microsoft Azure рекомендуется использовать управляемые удостоверения. Управляемые удостоверения безопасно проходят проверку подлинности в службах Azure без хранения учетных данных в коде приложения. Дополнительные сведения см. на следующих ресурсах:

Поддержка антифоргерии

Шаблон Blazor :

Компонент AntiforgeryToken отрисовывает маркер антифоргерии как скрытое поле, и этот компонент автоматически добавляется в экземпляры формы (EditForm). Дополнительные сведения см. в разделе ASP.NET Общие сведения о формах CoreBlazor.

Служба AntiforgeryStateProvider предоставляет доступ к маркеру антифоргерии, связанному с текущим сеансом. Вставляет службу и вызывает его GetAntiforgeryToken() метод для получения текущего AntiforgeryRequestToken. Дополнительные сведения см. в статье Вызов веб-API в приложении ASP.NET Core Blazor.

Blazor сохраняет маркеры запроса в состоянии компонента, что гарантирует, что маркеры защиты доступны для интерактивных компонентов, даже если у них нет доступа к запросу.

Примечание.

Устранение неполадок с антифоргерией требуется только при отправке данных формы на сервер, закодированный как application/x-www-form-urlencoded, multipart/form-dataили text/plain так как они являются единственными допустимыми энктипами формы.

Дополнительные сведения см. на следующих ресурсах:

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

Blazor использует существующие механизмы проверки подлинности ASP.NET Core для установки пользователя identity. Точный механизм зависит от того, как Blazor размещено приложение, на стороне сервера или на стороне клиента.

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

Интерактивная отрисовка на стороне Blazor сервера работает над подключением SignalR к клиенту. Проверка подлинности в приложениях на основе SignalR выполняется при установлении подключения. Проверка подлинности может быть основана на маркере cookie или другом маркере носителя, но проверка подлинности осуществляется через SignalR концентратор и полностью в пределах канала.

Встроенная или настраиваемая AuthenticationStateProvider служба получает данные о состоянии проверки подлинности из ASP.NET Core HttpContext.User. Так состояние проверки подлинности интегрируется с существующими соответствующими механизмами проверки подлинности ASP.NET Core.

Дополнительные сведения о проверке подлинности на стороне сервера см. в разделе "Безопасные ASP.NET Основных приложений" на стороне Blazor сервера.

IHttpContextAccessor/HttpContext в Razor компонентах

IHttpContextAccessor необходимо избежать интерактивной отрисовки, так как не существует допустимой HttpContext возможности.

IHttpContextAccessor можно использовать для компонентов, которые статически отрисовываются на сервере. Тем не менее, мы рекомендуем избегать его, если это возможно.

HttpContext можно использовать в качестве каскадного параметра только в статически отрисованных корневых компонентах для общих задач, таких как проверка и изменение заголовков или других свойств компонента App (Components/App.razor). Значение всегда null предназначено для интерактивной отрисовки.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

В сценариях, где HttpContext требуется в интерактивных компонентах, рекомендуется передавать данные через постоянное состояние компонента с сервера. Дополнительные сведения см . на стороне сервера ASP.NET Основных Blazor дополнительных сценариев безопасности.

Не используйте IHttpContextAccessor/HttpContext непосредственно или косвенно в Razor компонентах серверных Blazor приложений. Blazor приложения выполняются вне контекста конвейера ASP.NET Core. Он HttpContext не гарантируется, что он доступен в пределах приложения IHttpContextAccessorи HttpContext не гарантируется, что он будет содержать контекст, который запустил Blazor приложение.

Рекомендуемый подход для передачи состояния Blazor запроса приложению осуществляется через параметры корневого компонента во время первоначальной отрисовки приложения. Кроме того, приложение может скопировать данные в службу с областью действия в событии жизненного цикла инициализации корневого компонента для использования в приложении. Дополнительные сведения см . на стороне сервера ASP.NET Основных Blazor дополнительных сценариев безопасности.

Критически важный аспект безопасности на стороне Blazor сервера заключается в том, что пользователь, подключенный к заданному каналу, может быть обновлен в какой-то момент после Blazor установки канала, но IHttpContextAccessorне обновляется. Дополнительные сведения об устранении этой ситуации с пользовательскими службами см. в дополнительных сценариях безопасности на стороне сервера ASP.NET CoreBlazor.

Общее состояние

Серверные Blazor приложения живут в памяти сервера, а несколько сеансов приложений размещаются в одном процессе. Для каждого сеанса Blazor приложения запускает канал с собственной областью контейнера внедрения зависимостей, поэтому службы с областью действия уникальны для каждого Blazor сеанса.

Предупреждение

Не рекомендуется совместное использование состояния приложениями на одном сервере с помощью отдельных служб, если только вы не принимаете строгие меры предосторожности, поскольку при таком подходе могут возникать уязвимости, например утечка состояния пользователя между каналами.

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

Общие рекомендации по управлению состоянием см. в разделе ASP.NET Core Blazor State Management.

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

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

Добавьте следующий код:

Для обработки проверки подлинности используйте встроенную или пользовательскую AuthenticationStateProvider службу.

Дополнительные сведения о проверке подлинности на стороне клиента см. в статье Secure ASP.NET Core Blazor WebAssembly.

Служба AuthenticationStateProvider

AuthenticationStateProvider — это базовая служба, используемая компонентом AuthorizeView и каскадными службами проверки подлинности для получения состояния проверки подлинности для пользователя.

AuthenticationStateProvider — это базовая служба, используемая компонентом AuthorizeView и CascadingAuthenticationState компонентом для получения состояния проверки подлинности для пользователя.

Обычно вы не используете AuthenticationStateProvider напрямую. Выберите подход с использованием компонента AuthorizeView или Task<AuthenticationState>, как описано далее в этой статье. Основной недостаток при использовании AuthenticationStateProvider напрямую заключается в том, что компонент не получает автоматического уведомления при изменении базовых данных о состоянии аутентификации.

Сведения о реализации пользовательского AuthenticationStateProviderрежима см. в разделе ASP.NET Состояние проверки подлинности CoreBlazor, включающее рекомендации по реализации уведомлений об изменении состояния проверки подлинности пользователей.

Получение данных субъекта-участника утверждений пользователя

Служба AuthenticationStateProvider может предоставить данные текущего ClaimsPrincipal пользователя, как показано в следующем примере.

ClaimsPrincipalData.razor:

@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@surname</p>

@code {
    private string? authMessage;
    private string? surname;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

В предыдущем примере:

  • ClaimsPrincipal.Claims возвращает утверждения пользователя (claims) для отображения в пользовательском интерфейсе.
  • Строка, которая получает фамилию пользователя (surname) вызывает ClaimsPrincipal.FindAll с предикатом для фильтрации утверждений пользователя.
@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@surname</p>

@code {
    private string? authMessage;
    private string? surname;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

Если user.Identity.IsAuthenticated имеет значение true, а пользователь является ClaimsPrincipal, можно перечислить утверждения и оценить членство в ролях.

Дополнительные сведения о внедрении зависимостей и службах см. в статье Внедрение зависимостей ASP.NET Core Blazor и Внедрение зависимостей в ASP.NET Core. Сведения о реализации пользовательского AuthenticationStateProviderинтерфейса см. в разделе ASP.NET Состояние проверки подлинности CoreBlazor.

Предоставление состояния аутентификации в качестве каскадного параметра

Если данные о состоянии проверки подлинности необходимы для процедурной логики, например при выполнении действия, активированного пользователем, получите данные о состоянии проверки подлинности, определив каскадный параметр типа Task<AuthenticationState>, как показано в следующем примере.

CascadeAuthState.razor:

@page "/cascade-auth-state"

<h1>Cascade Auth State</h1>

<p>@authMessage</p>

@code {
    private string authMessage = "The user is NOT authenticated.";

    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user?.Identity is not null && user.Identity.IsAuthenticated)
            {
                authMessage = $"{user.Identity.Name} is authenticated.";
            }
        }
    }
}
@page "/cascade-auth-state"

<h1>Cascade Auth State</h1>

<p>@authMessage</p>

@code {
    private string authMessage = "The user is NOT authenticated.";

    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user?.Identity is not null && user.Identity.IsAuthenticated)
            {
                authMessage = $"{user.Identity.Name} is authenticated.";
            }
        }
    }
}

Если user.Identity.IsAuthenticated имеет значение true, можно перечислить утверждения и оценить членство в ролях.

Task<AuthenticationState> Настройте каскадный параметр с помощью AuthorizeRouteView каскадных служб проверки подлинности и каскадных служб проверки подлинности.

При создании Blazor приложения из одного из Blazor шаблонов проектов с включенной проверкой подлинности приложение включает AuthorizeRouteView и вызов AddCascadingAuthenticationState , показанный в следующем примере. Клиентское Blazor приложение также включает необходимые регистрации служб. Дополнительные сведения представлены в разделе "Настройка несанкционированного содержимого Router " в разделе компонента .

<Router ...>
    <Found ...>
        <AuthorizeRouteView RouteData="routeData" 
            DefaultLayout="typeof(Layout.MainLayout)" />
        ...
    </Found>
</Router>

Program В файле зарегистрируйте каскадные службы проверки подлинности:

builder.Services.AddCascadingAuthenticationState();

Настройте каскадный Task<> AuthenticationStateпараметр с помощью AuthorizeRouteView компонентов и CascadingAuthenticationState компонентов.

При создании Blazor приложения из одного из Blazor шаблонов проектов с включенной проверкой подлинности приложение включает AuthorizeRouteView и CascadingAuthenticationState компоненты, показанные в следующем примере. Клиентское Blazor приложение также включает необходимые регистрации служб. Дополнительные сведения представлены в разделе "Настройка несанкционированного содержимого Router " в разделе компонента .

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView RouteData="routeData" 
                DefaultLayout="typeof(MainLayout)" />
            ...
        </Found>
    </Router>
</CascadingAuthenticationState>

Примечание.

В выпуске ASP.NET Core 5.0.1 и дальнейших выпусках 5.x компонент Router содержит параметр PreferExactMatches со значением @true. Дополнительные сведения см. в статье Миграция с ASP.NET Core 3.1 на 5.0.

В клиентском Blazor приложении добавьте службы авторизации в Program файл:

builder.Services.AddAuthorizationCore();

В клиентском Blazor приложении добавьте параметры и службы авторизации в Program файл:

builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();

В серверном Blazor приложении службы для параметров и авторизации уже присутствуют, поэтому дальнейшие действия не требуются.

Авторизация

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

Доступ обычно предоставляется или запрещается в зависимости от следующих аспектов:

  • выполнена ли аутентификация (выполнен ли вход);
  • есть ли у пользователя определенная роль;
  • есть ли у пользователя определенное утверждение;
  • выполняются ли требования политики.

Каждый из этих аспектов применяется здесь так же, как в приложениях ASP.NET Core MVC или Razor Pages. Дополнительные сведения о безопасности в ASP.NET Core вы найдете в статьях о безопасности и Identity в ASP.NET Core.

Компонент AuthorizeView

Компонент AuthorizeView избирательно демонстрирует содержимое пользовательского интерфейса в зависимости от того, авторизован ли пользователь. Этот подход полезен, если необходимо отображать данные только для пользователя и не нужно использовать его identity в процедурной логике.

Компонент предоставляет context переменную типа AuthenticationState (@context в Razor синтаксисе), которую можно использовать для доступа к сведениям о входе пользователя:

<AuthorizeView>
    <p>Hello, @context.User.Identity?.Name!</p>
</AuthorizeView>

Кроме того, можно указать другое содержимое для отображения, если пользователь не авторизован с помощью сочетания Authorized параметров и NotAuthorized параметров:

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
        <p><button @onclick="HandleClick">Authorized Only Button</button></p>
    </Authorized>
    <NotAuthorized>
        <p>You're not authorized.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    private void HandleClick() { ... }
}

AuthorizeView Хотя компонент управляет видимостью элементов на основе состояния авторизации пользователя, он не обеспечивает безопасность самого обработчика событий. В предыдущем примере HandleClick метод связан только с кнопкой, видимой авторизованным пользователям, но не запрещает вызывать этот метод из других мест. Чтобы обеспечить безопасность на уровне метода, реализуйте дополнительную логику авторизации в самом обработчике или в соответствующем API.

Razor компоненты содержимого Blazor Web Appникогда не отображаются <NotAuthorized> при сбое авторизации на стороне сервера во время отрисовки на стороне статического сервера (статический SSR). Серверный конвейер ASP.NET Core обрабатывает авторизацию на сервере. Используйте методы на стороне сервера для обработки несанкционированных запросов. Дополнительные сведения см. в режимах отрисовки ASP.NET CoreBlazor.

Предупреждение

Разметка на стороне клиента и методы, связанные с нимAuthorizeView, защищены только от просмотра и выполнения в отрисованном пользовательском интерфейсе в клиентских Blazor приложениях. Чтобы защитить авторизованное содержимое и безопасные методы на стороне Blazorклиента, содержимое обычно предоставляется безопасным, авторизованным вызовом веб-API к API сервера и никогда не хранится в приложении. Дополнительные сведения см. в статье "Вызов веб-API" из приложения ASP.NET Core Blazor и дополнительных сценариев безопасности ASP.NET CoreBlazor WebAssembly.

Содержимое Authorized и NotAuthorized может включать произвольные элементы, например другие интерактивные компоненты.

Условия авторизации, такие как роли или правила для выбора вариантов пользовательского интерфейса и доступа к ним, описаны в разделе об авторизации.

Если условия авторизации не указаны, AuthorizeView использует политику по умолчанию:

  • Пользователи, прошедшие проверку подлинности (вошедшего в систему), авторизованы.
  • Пользователи, не прошедшие проверку подлинности (вошедшего в систему), не несанкционированны.

Компонент AuthorizeView можно использовать в компоненте NavMenu (Shared/NavMenu.razor) для отображения компонента NavLink (NavLink), но следует учитывать, что при использовании этого подхода удаляется только элемент списка из отображаемых выходных данных. Пользователь по-прежнему может переходить к компоненту. Реализуйте авторизацию отдельно в целевом компоненте.

Авторизация на основе ролей и политик

Компонент AuthorizeView поддерживает авторизацию на основе ролей или политик.

Для авторизации на основе ролей используйте Roles параметр. В следующем примере пользователь должен иметь утверждение роли для Admin ролей или Superuser ролей:

<AuthorizeView Roles="Admin, Superuser">
    <p>You have an 'Admin' or 'Superuser' role claim.</p>
</AuthorizeView>

Чтобы требовать, чтобы у пользователя были Admin утверждения ролей и Superuser роли, вложенные AuthorizeView компоненты:

<AuthorizeView Roles="Admin">
    <p>User: @context.User</p>
    <p>You have the 'Admin' role claim.</p>
    <AuthorizeView Roles="Superuser" Context="innerContext">
        <p>User: @innerContext.User</p>
        <p>You have both 'Admin' and 'Superuser' role claims.</p>
    </AuthorizeView>
</AuthorizeView>

Предыдущий код устанавливает Context для внутреннего AuthorizeView компонента, чтобы предотвратить конфликт контекста AuthenticationState . Контекст AuthenticationState осуществляется во внешнем AuthorizeView с помощью стандартного подхода для доступа к контексту (@context.User). Доступ к контексту осуществляется внутри AuthorizeView с именованным innerContext контекстом (@innerContext.User).

Дополнительные сведения, включая инструкции по настройке, см. в статье Авторизация на основе ролей в ASP.NET Core.

Для авторизации на основе политик используйте Policy параметр с одним именем политики:

<AuthorizeView Policy="Over21">
    <p>You satisfy the 'Over21' policy.</p>
</AuthorizeView>

Чтобы справиться с ситуацией, когда пользователь должен удовлетворить одну из нескольких политик, создайте политику, которая подтверждает, что пользователь удовлетворяет другим политикам.

Чтобы справиться с ситуацией, когда пользователь должен одновременно удовлетворять несколько политик, выполните один из следующих подходов:

  • Создайте политику для AuthorizeView подтверждения того, что пользователь удовлетворяет нескольким другим политикам.

  • Вложение политик в несколько AuthorizeView компонентов:

    <AuthorizeView Policy="Over21">
        <AuthorizeView Policy="LivesInCalifornia">
            <p>You satisfy the 'Over21' and 'LivesInCalifornia' policies.</p>
        </AuthorizeView>
    </AuthorizeView>
    

Авторизация на основе утверждений считается особым случаем авторизации на основе политик. Например, вы можете определить политику, которая требует наличия определенного утверждения у пользователя. Дополнительные сведения см. в статье Авторизация на основе политик в ASP.NET Core.

Если ни Policy не Roles указано, AuthorizeView используется политика по умолчанию:

  • Пользователи, прошедшие проверку подлинности (вошедшего в систему), авторизованы.
  • Пользователи, не прошедшие проверку подлинности (вошедшего в систему), не несанкционированны.

Так как сравнения строк .NET чувствительны к регистру, соответствующие имена ролей и политик также учитывает регистр. Например, (верхний регистрA) не рассматривается как та же роль, Admin что admin и (строчная).a

Регистр Pascal обычно используется для имен ролей и политик (например, BillingAdministrator), но использование регистра Pascal не является строгим требованием. Разрешены различные схемы регистра, такие как верблюдьи случаи, кебаб и змеиный случай. Использование пробелов в именах ролей и политик является необычным, но разрешено платформой. Например, billing administrator это необычный формат имени роли или политики в приложениях .NET, но это допустимая роль или имя политики.

Содержимое, отображаемое при асинхронной аутентификации

Blazor позволяет асинхронно определять состояние проверки подлинности. Основной сценарий этого подхода — в клиентских Blazor приложениях, которые запрашивают внешнюю конечную точку для проверки подлинности.

При выполнении AuthorizeView проверки подлинности не отображается содержимое. Чтобы отобразить содержимое во время проверки подлинности, назначьте содержимое параметру Authorizing :

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
    </Authorized>
    <Authorizing>
        <p>You can only see this content while authentication is in progress.</p>
    </Authorizing>
</AuthorizeView>

Этот подход обычно не применяется к приложениям на стороне Blazor сервера. Серверные Blazor приложения знают состояние проверки подлинности сразу после установки состояния. Authorizing содержимое может быть предоставлено в компоненте приложения AuthorizeView , но содержимое никогда не отображается.

Атрибут [Authorize]

Атрибут [Authorize] доступен в Razor компонентах:

@page "/"
@attribute [Authorize]

You can only see this if you're signed in.

Внимание

Используется [Authorize] только для @page компонентов, достигнутых через Blazor маршрутизатор. Авторизация выполняется только как аспект маршрутизации и не для дочерних компонентов, которые отображаются на странице. Чтобы разрешить отображение конкретных частей на странице, используйте вместо этого AuthorizeView.

Атрибут [Authorize] также поддерживает авторизацию на основе ролей или политик. Для авторизации на основе ролей примените параметр Roles:

@page "/"
@attribute [Authorize(Roles = "Admin, Superuser")]

<p>You can only see this if you're in the 'Admin' or 'Superuser' role.</p>

Для авторизации на основе политик примените параметр Policy:

@page "/"
@attribute [Authorize(Policy = "Over21")]

<p>You can only see this if you satisfy the 'Over21' policy.</p>

Если ни Policy не Roles указано, [Authorize] используется политика по умолчанию:

  • Пользователи, прошедшие проверку подлинности (вошедшего в систему), авторизованы.
  • Пользователи, не прошедшие проверку подлинности (вошедшего в систему), не несанкционированны.

Если пользователь не авторизован и если приложение не настраивает несанкционированное содержимое с Router помощью компонента, платформа автоматически отображает следующее резервное сообщение:

Not authorized.

Авторизация ресурсов

Чтобы авторизовать пользователей для доступа к ресурсам, передайте данные маршрута запроса в параметр Resource в AuthorizeRouteView.

В содержимом Router.Found запрошенного маршрута:

<AuthorizeRouteView Resource="routeData" RouteData="routeData" 
    DefaultLayout="typeof(MainLayout)" />

Дополнительные сведения о том, как данные состояния авторизации передаются и используются в процедурной логике, см. в статье Предоставление состояния аутентификации в качестве каскадного параметра.

Когда объект AuthorizeRouteView получает данные маршрута для ресурса, политики авторизации получают доступ к RouteData.PageType и RouteData.RouteValues, в результате чего разрешается использовать настраиваемую логику для принятия решений об авторизации.

В следующем примере в AuthorizationOptions создается политика EditUser для конфигурации службы авторизации приложения (AddAuthorizationCore) с помощью следующей логики:

  • Определение того, существует ли значение маршрута с ключом id. Если ключ существует, значение маршрута сохраняется в value.
  • В переменной с именем id сохраните value в виде строки или задайте пустое строковое значение (string.Empty).
  • Если id не является пустой строкой, следует подтвердить, что условия политики соблюдены (возвращается true), если значение строки начинается с EMP. В противном случае следует подтвердить, что политика завершается ошибкой (возвращается false).

В файле Program:

  • Добавьте пространства имен для Microsoft.AspNetCore.Components и System.Linq:

    using Microsoft.AspNetCore.Components;
    using System.Linq;
    
  • Добавьте политику:

    options.AddPolicy("EditUser", policy =>
        policy.RequireAssertion(context =>
        {
            if (context.Resource is RouteData rd)
            {
                var routeValue = rd.RouteValues.TryGetValue("id", out var value);
                var id = Convert.ToString(value, 
                    System.Globalization.CultureInfo.InvariantCulture) ?? string.Empty;
    
                if (!string.IsNullOrEmpty(id))
                {
                    return id.StartsWith("EMP", StringComparison.InvariantCulture);
                }
            }
    
            return false;
        })
    );
    

Предыдущий пример — это упрощенная политика авторизации, используемая исключительно для демонстрации концепции с рабочим примером. Дополнительные сведения о создании и настройке политик авторизации см. в статье Авторизация на основе политик в ASP.NET Core.

В следующем компоненте EditUser ресурс в /users/{id}/edit имеет параметр маршрута для идентификатора пользователя ({id}). Компонент использует предыдущую политику авторизации EditUser, чтобы определить, будет ли значение маршрута id начинаться с EMP. Если id начинается с EMP, политика будет успешно применена, и доступ к компоненту будет разрешен. Если id начинается со значения, отличного от EMP, или если id является пустой строкой, то политика завершается ошибкой и компонент не загружается.

EditUser.razor:

@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h1>Edit User</h1>

<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

@code {
    [Parameter]
    public string? Id { get; set; }
}
@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h1>Edit User</h1>

<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

@code {
    [Parameter]
    public string? Id { get; set; }
}

Настройка несанкционированного содержимого Router с помощью компонента

Компонент Router вместе с компонентом AuthorizeRouteView позволяет приложению указать пользовательское содержимое для следующих ситуаций:

  • пользователь не удовлетворяет условию [Authorize], которое применено к компоненту Отображается разметка для элемента <NotAuthorized>. (атрибут [Authorize] описан в разделе Атрибут [Authorize]);
  • Выполняется асинхронная авторизация. Как правило, это означает, что выполняется проверка подлинности пользователя. Отображается разметка для элемента <Authorizing>.

Внимание

Blazor функции маршрутизатора, которые отображаются <NotAuthorized> и <NotFound> содержимое не работают во время отрисовки на стороне статического сервера (статический SSR), так как обработка запросов на ASP.NET Core по промежуточному по промежуточному слоям не обрабатывается, а Razor компоненты не отображаются вообще для несанкционированных или плохих запросов. Используйте методы на стороне сервера для обработки несанкционированных и плохих запросов во время статического SSR. Дополнительные сведения см. в режимах отрисовки ASP.NET CoreBlazor.

<Router ...>
    <Found ...>
        <AuthorizeRouteView ...>
            <NotAuthorized>
                ...
            </NotAuthorized>
            <Authorizing>
                ...
            </Authorizing>
        </AuthorizeRouteView>
    </Found>
</Router>

Содержимое Authorized и NotAuthorized может включать произвольные элементы, например другие интерактивные компоненты.

Примечание.

Для предыдущей процедуры требуется каскадная регистрация государственных служб проверки подлинности в файле приложения Program :

builder.Services.AddCascadingAuthenticationState();
<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView ...>
                <NotAuthorized>
                    ...
                </NotAuthorized>
                <Authorizing>
                    ...
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
    </Router>
</CascadingAuthenticationState>

Содержимое NotFound, Authorized и NotAuthorized может включать произвольные элементы, например другие интерактивные компоненты.

Если NotAuthorized содержимое не указано, AuthorizeRouteView используется следующее резервное сообщение:

Not authorized.

Приложение, созданное Blazor WebAssembly из шаблона проекта с включенной проверкой RedirectToLogin подлинности, включает компонент, расположенный в <NotAuthorized> содержимом Router компонента. Если пользователь не прошел проверку подлинности (context.User.Identity?.IsAuthenticated != true), RedirectToLogin компонент перенаправляет браузер в конечную точку authentication/login для проверки подлинности. Пользователь возвращается на запрошенный URL-адрес после проверки подлинности с identity помощью поставщика.

Процедурная логика

Если приложению нужно проверять правила авторизации в составе процедурной логики, используйте каскадный параметр с типом Task<AuthenticationState>, чтобы получить ClaimsPrincipal пользователя. Task<AuthenticationState> можно комбинировать для оценки политик с другими службами, например IAuthorizationService.

В следующем примере :

  • Выполняет user.Identity.IsAuthenticated код для пользователей, прошедших проверку подлинности (вошедшего в систему).
  • Выполняет user.IsInRole("admin") код для пользователей в роли "Администратор".
  • Выполняет (await AuthorizationService.AuthorizeAsync(user, "content-editor")).Succeeded код для пользователей, удовлетворяющих политике content-editor.

Серверное Blazor приложение включает соответствующие пространства имен при создании из шаблона проекта. В клиентском Blazor приложении подтвердите наличие Microsoft.AspNetCore.Authorization Microsoft.AspNetCore.Components.Authorization пространств имен в компоненте или в файле приложения _Imports.razor :

@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization

ProceduralLogic.razor:

@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService

<h1>Procedural Logic Example</h1>

<button @onclick="@DoSomething">Do something important</button>

@code {
    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    private async Task DoSomething()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user is not null)
            {
                if (user.Identity is not null && user.Identity.IsAuthenticated)
                {
                    // ...
                }

                if (user.IsInRole("Admin"))
                {
                    // ...
                }

                if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
                    .Succeeded)
                {
                    // ...
                }
            }
        }
    }
}
@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService

<h1>Procedural Logic Example</h1>

<button @onclick="@DoSomething">Do something important</button>

@code {
    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    private async Task DoSomething()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user is not null)
            {
                if (user.Identity is not null && user.Identity.IsAuthenticated)
                {
                    // ...
                }

                if (user.IsInRole("Admin"))
                {
                    // ...
                }

                if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
                    .Succeeded)
                {
                    // ...
                }
            }
        }
    }
}

Устранение неполадок

Распространенные ошибки

  • Для авторизации требуется каскадный параметр с типом Task<AuthenticationState>. Чтобы предоставить его, попробуйте использовать CascadingAuthenticationState.

  • Для authenticationStateTask возвращается значение null

Скорее всего, проект не был создан с помощью шаблона на стороне Blazor сервера с включенной проверкой подлинности.

В .NET 7 или более ранних версиях обтекайте <CascadingAuthenticationState> часть дерева пользовательского интерфейса, например вокруг маршрутизатора Blazor :

<CascadingAuthenticationState>
    <Router ...>
        ...
    </Router>
</CascadingAuthenticationState>

В .NET 8 или более поздней версии не используйте CascadingAuthenticationState компонент:

- <CascadingAuthenticationState>
      <Router ...>
          ...
      </Router>
- </CascadingAuthenticationState>

Вместо этого добавьте каскадные службы состояния проверки подлинности в коллекцию служб в Program файле:

builder.Services.AddCascadingAuthenticationState();

Компонент CascadingAuthenticationState (.NET 7 или более ранний) или службы, предоставляемые AddCascadingAuthenticationState (.NET 8 или более поздней версии), предоставляют Task<AuthenticationState> каскадный параметр, который, в свою очередь, получает от базовой AuthenticationStateProvider службы внедрения зависимостей.

личные сведения (PII).

Корпорация Майкрософт использует определение GDPR для персональных данных (GDPR 4.1) при обсуждении персональных данных (PII).

PiI ссылается на любую информацию, связанную с идентифицированным или идентифицируемым физическим лицом. Идентифицируемый физический человек — это тот, кто может быть идентифицирован, прямо или косвенно, с любым из следующих элементов:

  • Имя.
  • Идентификационный номер
  • Координаты расположения
  • Идентификатор в Сети
  • Другие конкретные факторы
    • Физически
    • Физиологический
    • Генетический
    • Психический (психологический)
    • Экономический
    • Культура
    • Общественный identity

Дополнительные ресурсы