Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье описывается, как авторизовать пользователей для доступа к ресурсам приложения.
В приложении ресурс обычно представлен классом C#, который содержит данные, хранящиеся в коллекции, например byte[] массив. Класс обычно содержит дополнительные метаданные, относящиеся к ресурсу, например уникальный идентификатор ресурса, даты, авторы, исходные сведения и понятное имя для отображения в пользовательском интерфейсе. Коллекция, содержащая данные ресурсов, обычно загружается из физического содержимого файла, объекта облачного хранилища, объекта в памяти или данных из базы данных.
Авторизация на основе ресурсов требует особого внимания в ASP.NET Core приложениях. Оценка атрибутов возникает перед привязкой данных и перед выполнением любого метода, загружающего ресурс. Декларативная авторизация с атрибутом [Authorize] не достаточно для авторизации на основе ресурсов. Вместо этого приложение должно вызвать пользовательский метод авторизации — подход, известный как императивная авторизация.
В этой статье используются примеры компонентов Razor и рассматриваются сценарии авторизации Blazor для ASP.NET Core 3.1 или более поздней версии. Сведения о руководствах по Razor Pages и MVC, которые применяются ко всем версиям ASP.NET Core, см. в следующих ресурсах:
- Авторизация на основе ресурсов в ASP.NET Core Razor Pages
- Авторизация на основе ресурсов в ASP.NET Core MVC
Примеры в этой статье используют основные конструкторы, доступные в C# 12 (.NET 8) или более поздней версии. Дополнительные сведения см. в разделах "Объявление первичных конструкторов для классов и структур" (учебник по документации по C#) и "Первичные конструкторы" (руководство по C#).
Пример приложения
Примером Blazor Web App для этой статьи является BlazorWebAppAuthorization пример приложения (dotnet/AspNetCore.Docs.Samples репозиторий GitHub) (как скачать). В примере приложения используются заполненные учетные записи с предварительно настроенными объектами документов для демонстрации примеров в этой статье. Дополнительные сведения см. в файле README примера (README.md).
Предостережение
В этом примере приложения используется база данных в памяти для хранения сведений о пользователях, которые не подходят для рабочих сценариев. Пример приложения предназначен только для демонстрационных целей и не должен использоваться в качестве отправной точки для рабочих приложений.
Использование императивной авторизации
Авторизация реализуется как IAuthorizationService, зарегистрированная в коллекции служб при запуске приложения платформой ASP.NET Core. Служба предоставляется Razor компонентам и другим классам с помощью внедрения зависимостей:
@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService
IAuthorizationService имеет две перегрузки метода AuthorizeAsync. Одна из перегрузок принимает имя ресурса и политики:
Task<AuthorizationResult> AuthorizeAsync(
ClaimsPrincipal user,
object resource,
string policyName);
Другая перегрузка принимает ресурс и коллекцию требований (IAuthorizationRequirement) для оценки:
Task<AuthorizationResult> AuthorizeAsync(
ClaimsPrincipal user,
object resource,
IEnumerable<IAuthorizationRequirement> requirements);
В следующем примере, который полностью описан в разделе "Создание обработчика на основе ресурсов ", защищенный ресурс загружается в пользовательский Document объект.
AuthorizeAsync перегрузка вызывается, чтобы определить, имеет ли текущий пользователь доступ к документу в соответствии с политикой авторизации "SameAuthorPolicy". Если authorizationResult.Succeeded это trueтак, пользователь авторизован для документа, так как он создал документ (Document.Author соответствует пользователю Name):
protected override async Task OnParametersSetAsync()
{
var user = (await AuthStateProvider.GetAuthenticationStateAsync()).User;
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
var document = DocumentRepository.Find(DocumentId);
...
var authorizationResult = await AuthorizationService
.AuthorizeAsync(user, document, "SameAuthorPolicy");
...
}
}
Создайте обработчик на основе ресурсов
Создание обработчика авторизации на основе ресурсов аналогично созданию обработчика простых требований. Создайте пользовательский класс требований и реализуйте класс обработчика требований. Дополнительные сведения о создании класса требований см. в разделе "Авторизация на основе политик: требования".
Используется следующий демонстрационный Document класс:
namespace BlazorWebAppAuthorization.Models;
public class Document
{
public string? Author { get; set; }
public byte[]? Content { get; set; }
public Guid ID { get; set; }
public string? Title { get; set; }
}
Класс обработчика указывает требование и тип ресурса. В следующем примере показан обработчик, используюющий SameAuthorRequirement требование и Document ресурс.
Services/DocumentAuthorizationHandler.cs:
using Microsoft.AspNetCore.Authorization;
using BlazorWebAppAuthorization.Models;
namespace BlazorWebAppAuthorization.Services;
public class DocumentAuthorizationHandler :
AuthorizationHandler<SameAuthorRequirement, Document>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
SameAuthorRequirement requirement,
Document resource)
{
if (context.User.Identity?.Name == resource.Author)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
public class SameAuthorRequirement : IAuthorizationRequirement { }
Зарегистрируйте требование и обработчик в Program.cs:
builder.Services.AddAuthorizationBuilder()
.AddPolicy("SameAuthorPolicy", policy =>
policy.Requirements.Add(new SameAuthorRequirement()));
builder.Services.AddSingleton<IAuthorizationHandler, DocumentAuthorizationHandler>();
Зарегистрируйте требование и обработчик в Startup.ConfigureServices:
services.AddAuthorization(options =>
{
options.AddPolicy("SameAuthorPolicy", policy =>
policy.Requirements.Add(new SameAuthorRequirement()));
});
services.AddSingleton<IAuthorizationHandler, DocumentAuthorizationHandler>();
Дополнительные сведения о создании политик авторизации см. в разделе Полиси на основе авторизации в ASP.NET Core.
Следующий AccessDocument компонент вызывает перегрузку AuthorizeAsync , чтобы определить, разрешен ли текущий пользователь просматривать документ на основе политики авторизации "SameAuthorPolicy". Если authorizationResult.Succeeded это trueтак, пользователь авторизован для документа, так как он создал документ (Document.Author соответствует пользователю Name).
Pages/AccessDocument.razor:
@page "/access-document/{documentId}"
@using Microsoft.AspNetCore.Authorization
@using BlazorWebAppAuthorization.Data
@inject AuthenticationStateProvider AuthStateProvider
@inject IAuthorizationService AuthorizationService
@inject IDocumentRepository DocumentRepository
<h1>Access Document</h1>
<AuthorizeView>
<Authorized>
<p>Hello, @context.User.Identity?.Name!</p>
<p>@message</p>
</Authorized>
<NotAuthorized>
<p>You're not authorized to access this page.</p>
</NotAuthorized>
</AuthorizeView>
@code {
private string? message;
[Parameter]
public string? DocumentId { get; set; }
protected override async Task OnParametersSetAsync()
{
var user = (await AuthStateProvider.GetAuthenticationStateAsync()).User;
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
var document = DocumentRepository.Find(DocumentId);
if (document == null)
{
message = "Document not found.";
return;
}
var authorizationResult = await AuthorizationService
.AuthorizeAsync(user, document, "SameAuthorPolicy");
message = authorizationResult.Succeeded
? $"You are authorized for document {DocumentId}."
: $"You are NOT authorized for document {DocumentId}.";
}
}
}
В приложении-примере каждый пользователь приложения имеет право доступа к предварительно созданному документу, автором которого он является.
Требования к операционной деятельности
Чтобы принимать решения на основе результатов операций CRUD (создание, чтение, обновление, удаление), используйте вспомогательный OperationAuthorizationRequirement класс. Вспомогательный класс позволяет создавать один обработчик вместо отдельного класса для каждого типа операции.
Operations Следующий класс устанавливает все четыре типа операций CRUD:
using Microsoft.AspNetCore.Authorization.Infrastructure;
public static class Operations
{
public static readonly OperationAuthorizationRequirement Create =
new() { Name = nameof(Create) };
public static readonly OperationAuthorizationRequirement Delete =
new() { Name = nameof(Delete) };
public static readonly OperationAuthorizationRequirement Read =
new() { Name = nameof(Read) };
public static readonly OperationAuthorizationRequirement Update =
new() { Name = nameof(Update) };
}
Следующий обработчик авторизации DocumentAuthorizationCrudHandler проверяет операцию, используя ресурс, в некоторых случаях данные пользователя (роль) и свойство Name требования:
- Все пользователи могут читать документы.
- Только пользователи с ролью
Adminмогут создавать и обновлять документы. - Только пользователи с ролью
SuperUserмогут удалять документы.
Services/DocumentAuthorizationCrudHandler.cs:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;
using BlazorWebAppAuthorization.Models;
namespace BlazorWebAppAuthorization.Services;
public class DocumentAuthorizationCrudHandler :
AuthorizationHandler<OperationAuthorizationRequirement, Document>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
OperationAuthorizationRequirement requirement,
Document resource)
{
if (requirement.Name == Operations.Create.Name &&
context.User.IsInRole("Admin"))
{
context.Succeed(requirement);
}
if (requirement.Name == Operations.Delete.Name &&
context.User.IsInRole("SuperUser"))
{
context.Succeed(requirement);
}
if (requirement.Name == Operations.Read.Name)
{
context.Succeed(requirement);
}
if (requirement.Name == Operations.Update.Name &&
context.User.IsInRole("Admin"))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
Где службы зарегистрированы в приложении:
builder.Services.AddSingleton<IAuthorizationHandler, DocumentAuthorizationCrudHandler>();
Вызовите перегрузку метода AuthorizeAsync, передав операцию, чтобы вернуть результат авторизации.
Чтобы получить разрешение на создание документа:
var authorizationResult = await AuthorizationService
.AuthorizeAsync(user, document, Operations.Create);
Для авторизации для чтения документа:
var authorizationResult = await AuthorizationService
.AuthorizeAsync(user, document, Operations.Read);
Для авторизации для удаления документа:
var authorizationResult = await AuthorizationService
.AuthorizeAsync(user, document, Operations.Delete);
Для авторизации на обновление документа:
var authorizationResult = await AuthorizationService
.AuthorizeAsync(user, document, Operations.Update);
На странице примера приложенияAccessDocumentCrud:
- Leela (
leela@contoso.com), какAdminиSuperUser, может выполнять полные операции CRUD с ресурсами. - Гарри (
harry@contoso.com), имея только рольAdmin, может создавать, читать и обновлять ресурсы. - Сара (
sarah@contoso.com), как только aSuperUser, может удалять и считывать ресурсы.
ASP.NET Core