Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Quando uma identidade é criada para um usuário de aplicativo ao entrar em um aplicativo, o provedor de identidade pode atribuir uma ou mais declarações à identidade do usuário. Uma declaração é um par de nome/valor que representa o que o assunto (um usuário, um aplicativo ou serviço, ou um dispositivo/computador) é, e não o que o assunto pode fazer. Uma declaração pode ser avaliada pelo aplicativo para determinar os direitos de acesso a dados e outros recursos protegidos durante o processo de autorização e também pode ser usada para tomar ou expressar decisões de autenticação sobre um assunto. Uma identidade pode conter várias declarações com vários valores e pode conter várias declarações do mesmo tipo. Este artigo explica como adicionar verificações de declarações para autorização em um aplicativo ASP.NET Core.
Este artigo usa exemplos de componente do Razor e se concentra em cenários de autorização do Blazor. Para obter diretrizes adicionaisBlazor, consulte a seção Conteúdo relacionado. Para obter diretrizes sobre Razor Pages e MVC, consulte os seguintes recursos:
- Autorização baseada em declarações no ASP.NET Core Razor Pages
- Autorização baseada em declarações no MVC do ASP.NET Core
Aplicativo de exemplo
O exemplo Blazor Web App deste artigo é o aplicativo de exemplo BlazorWebAppAuthorization (repositório GitHub dotnet/AspNetCore.Docs.Samples) (como baixar). O aplicativo de exemplo usa contas semeadas com declarações pré-configuradas para demonstrar a maioria dos exemplos neste artigo. Para obter mais informações, consulte o arquivo README do exemplo (README.md).
Cuidado
Este aplicativo de exemplo usa um banco de dados na memória para armazenar informações do usuário, o que não é adequado para cenários de produção. O aplicativo de exemplo destina-se apenas a fins de demonstração e não deve ser usado como ponto de partida para aplicativos de produção.
Adicionar verificações de declaração
Verificações de autorização baseadas em declaração:
- São declarativas e especificam declarações por meio de políticas que o usuário atual deve apresentar para acessar o recurso solicitado.
- São aplicados a componentes do Razor (exemplos neste artigo), Razor Pages ou controladores MVC ou ações dentro de um controlador.
O componente AuthorizeView (componente AuthorizeView na documentação do Blazor) oferece suporte à autorização baseada em política, em que a política requer uma ou mais declarações. Como alternativa, uma autorização baseada em declarações por meio de uma ou mais verificações de política pode ser configurada usando [Authorize] atributos em componentes do Razor. O desenvolvedor deve criar e registrar uma política expressando os requisitos de declarações. Esta seção aborda conceitos básicos. Para obter cobertura completa, consulte ASP.NET Core Blazor autenticação e autorização.
O tipo mais simples de política de reivindicação procura a presença de uma reivindicação e não verifica o valor.
O registro da política ocorre como parte da configuração do serviço de autorização no arquivo do Program aplicativo:
builder.Services.AddAuthorizationBuilder()
.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
Observação
WebApplicationBuilder.ConfigureApplication (reference source) adiciona automaticamente uma chamada para UseAuthorization quando IAuthorizationHandlerProvider é registrado, o que tem sido o comportamento do ASP.NET Core desde o lançamento do .NET 8. Portanto, chamar UseAuthorization explicitamente para aplicativos Blazor do lado do servidor no .NET 8 ou posterior é tecnicamente redundante, mas a chamada não é prejudicial. Chamá-la no código do desenvolvedor depois que ela já tiver sido chamada pela estrutura não funciona.
Observação
Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas.
O registro da política ocorre como parte da configuração do serviço de autorização no arquivo do Program aplicativo:
builder.Services.AddAuthorizationBuilder()
.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
Em aplicativos Blazor Server, chame UseAuthorization após a linha que chama UseAuthentication (se estiver presente):
app.UseAuthentication(); // Only present if not called internally
app.UseAuthorization();
O registro da política ocorre como parte da configuração do serviço de autorização em Startup.ConfigureServices (Startup.cs):
services.AddAuthorization(options =>
{
options.AddPolicy("EmployeeOnly", policy =>
policy.RequireClaim("EmployeeNumber"));
});
Nos aplicativos Blazor Server, chame UseAuthorization em Startup.Configure após a linha que chama UseAuthentication (se presente):
app.UseAuthentication(); // Only present if not called internally
app.UseAuthorization();
Os aplicativos Blazor WebAssembly chamam AddAuthorizationCore no arquivo Program para adicionar serviços de autorização:
builder.Services.AddAuthorizationCore();
Aplique a política usando a Policy propriedade no [Authorize] atributo para especificar o nome da política. No exemplo a seguir, a política EmployeeOnly verifica a presença de uma declaração EmployeeNumber na identidade atual:
Para autorização baseada em política com um componente AuthorizeView, use o parâmetro AuthorizeView.Policy com um único nome de política.
Pages/PassEmployeeOnlyPolicyWithAuthorizeView.razor:
@page "/pass-employeeonly-policy-with-authorizeview"
<h1>Pass 'EmployeeOnly' policy with AuthorizeView</h1>
<AuthorizeView Policy="EmployeeOnly">
<Authorized>
<p>You satisfy the 'EmployeeOnly' policy.</p>
</Authorized>
<NotAuthorized>
<p>You <b>don't</b> satisfy the 'EmployeeOnly' policy.</p>
</NotAuthorized>
</AuthorizeView>
Como alternativa, aplique a política usando a Policy propriedade no [Authorize] atributo para especificar o nome da política. No exemplo a seguir, a política EmployeeOnly verifica a presença de uma declaração EmployeeNumber na identidade atual:
Pages/PassEmployeeOnlyPolicyWithAuthorizeAttribute.razor:
@page "/pass-employeeonly-policy-with-authorize-attribute"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EmployeeOnly")]
<h1>Pass 'EmployeeOnly' policy with [Authorize] attribute</h1>
<p>You satisfy the 'EmployeeOnly' policy.</p>
Você pode especificar uma lista de valores permitidos ao criar uma política. A política a seguir só passa para funcionários cujo número de funcionário seja 1, 2, 3, 4 ou 5:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddAuthorizationBuilder()
.AddPolicy("Founders", policy =>
policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("Founders", policy =>
policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
services.AddAuthorization(options =>
{
options.AddPolicy("Founder", policy =>
policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
});
Pages/PassFounderPolicyWithAuthorizeView.razor:
@page "/pass-founder-policy-with-authorizeview"
<h1>Pass 'Founder' policy with AuthorizeView</h1>
<AuthorizeView Policy="Founder">
<Authorized>
<p>You satisfy the 'Founder' policy.</p>
</Authorized>
<NotAuthorized>
<p>You <b>don't</b> satisfy the 'Founder' policy.</p>
</NotAuthorized>
</AuthorizeView>
Adicionar uma verificação de declaração genérica
Se o valor da declaração não for um único valor ou você precisar de uma lógica de avaliação de declaração mais flexível, como correspondência de padrões, verificação do emissor da declaração ou análise de valores de declaração complexos, use RequireAssertion com HasClaim. Por exemplo, a política a seguir exige que a declaração do email usuário termine com um domínio específico:
builder.Services.AddAuthorizationBuilder()
.AddPolicy("ContosoOnly", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c =>
c.Type == "email" &&
c.Value.EndsWith("@contoso.com", StringComparison.OrdinalIgnoreCase))));
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("ContosoOnly", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c =>
c.Type == "email" &&
c.Value.EndsWith("@contoso.com", StringComparison.OrdinalIgnoreCase))));
});
services.AddAuthorization(options =>
{
options.AddPolicy("ContosoOnly", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c =>
c.Type == "email" &&
c.Value.EndsWith("@contoso.com", StringComparison.OrdinalIgnoreCase))));
});
Para obter mais informações, consulte Autorização baseada emPolicy em ASP.NET Core.
Avaliar várias políticas
Várias políticas são aplicadas por meio de vários AuthorizeView componentes. O componente interno exige que o usuário passe sua política e todas as políticas dos componentes pai de AuthorizeView.
O exemplo a seguir:
- Requer uma política
CustomerServiceMember, que indica que o usuário está no departamento de atendimento ao cliente da organização, porque ele tem uma declaração deDepartmentcom um valor deCustomer Service. - Também requer uma política
HumanResourcesMember, que indica que o usuário está no departamento de recursos humanos da organização, porque ele tem uma declaração deDepartmentcom um valor deHuman Resources.
No arquivo Program do aplicativo:
builder.Services.AddAuthorizationBuilder()
.AddPolicy("CustomerServiceMember", policy =>
policy.RequireClaim("Department", "Customer Service"))
.AddPolicy("HumanResourcesMember", policy =>
policy.RequireClaim("Department", "Human Resources"));
No arquivo Program do aplicativo:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("CustomerServiceMember", policy =>
policy.RequireClaim("Department", "Customer Service"));
options.AddPolicy("HumanResourcesMember", policy =>
policy.RequireClaim("Department", "Human Resources"));
});
Em Startup.ConfigureServices (Startup.cs):
services.AddAuthorization(options =>
{
options.AddPolicy("CustomerServiceMember", policy =>
policy.RequireClaim("Department", "Customer Service"));
options.AddPolicy("HumanResourcesMember", policy =>
policy.RequireClaim("Department", "Human Resources"));
});
O exemplo a seguir usa AuthorizeView componentes.
Pages/PassCustomerServiceMemberAndHumanResourcesMemberPoliciesWithAuthorizeViews.razor:
@page "/pass-customerservicemember-and-humanresourcesmember-policies-with-authorizeviews"
<h1>Pass 'CustomerServiceMember' and 'HumanResourcesMember' policies with AuthorizeViews</h1>
<AuthorizeView Policy="CustomerServiceMember">
<Authorized>
<p>User: @context.User.Identity?.Name</p>
<AuthorizeView Policy="HumanResourcesMember" Context="innerContext">
<Authorized>
<p>
You satisfy the 'CustomerServiceMember' and 'HumanResourcesMember' policies.
</p>
</Authorized>
<NotAuthorized>
<p>
You satisfy the 'CustomerServiceMember' policy, but you <b>don't</b> satisfy
the 'HumanResourcesMember' policy.
</p>
</NotAuthorized>
</AuthorizeView>
</Authorized>
<NotAuthorized>
<p>
You <b>don't</b> satisfy the 'CustomerServiceMember' policy.
</p>
</NotAuthorized>
</AuthorizeView>
O exemplo a seguir usa atributos[Authorize].
Pages/PassCustomerServiceMemberAndHumanResourcesMemberPoliciesWithAuthorizeAttributes.razor:
@page "/pass-customerservicemember-and-humanresourcesmember-policies-with-authorize-attributes"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "CustomerServiceMember")]
@attribute [Authorize(Policy = "HumanResourcesMember")]
<h1>
Pass 'CustomerServiceMember' and 'HumanResourcesMember' policies with [Authorize] attributes
</h1>
<p>
You satisfy the 'CustomerServiceMember' and 'HumanResourcesMember' policies.
</p>
Para políticas mais complicadas, como interpretar uma declaração de data de nascimento, calcular uma idade a partir dela e verificar se a idade é 21 anos ou mais, utilize RequireAssertion ou escreva manipuladores de política personalizados. Manipuladores de política personalizados são úteis quando você precisa de acesso a serviços injetados por dependência ou deseja um componente de autorização reutilizável e testável.
Diferenciação de maiúsculas e minúsculas da declaração
Os valores de reivindicação são comparados usando StringComparison.Ordinal. Isso significa que Admin (maiúscula A) e admin (minúscula a) são sempre considerados papéis diferentes, independentemente de qual manipulador de autenticação criou a identidade.
Separadamente, a comparação de tipo de declaração (usada para localizar declarações de função por seu tipo de reivindicação, como http://schemas.microsoft.com/ws/2008/06/identity/claims/role) pode diferenciar maiúsculas de minúsculas ou não, dependendo da implementação de ClaimsIdentity. Com Microsoft.IdentityModel no ASP.NET Core 8.0 ou posterior (usado por AddJwtBearer, AddOpenIdConnect, AddWsFederation e AddMicrosoftIdentityWebApp/AddMicrosoftIdentityWebApi), CaseSensitiveClaimsIdentity é produzido durante a validação de tokens, que usa a correspondência de tipos de declaração que diferencia maiúsculas de minúsculas.
O ClaimsIdentity padrão fornecido pelo .NET runtime (usado na maioria dos casos, incluindo todos os fluxos baseados em cookie) ainda usa a correspondência de tipos de declaração que não diferencia maiúsculas de minúsculas.
Na prática, essa distinção raramente importa para autorização de função porque o tipo de declaração de função é definido uma vez durante a criação da identidade e correspondido consistentemente. Sempre use maiúsculas e minúsculas de forma consistente para nomes de funções e tipos de declaração para evitar problemas sutis.
Conteúdo relacionado
- ASP.NET Core Blazor autenticação e autorização
- ASP.NET Core Blazor estado de autenticação
- ASP.NET Core Blazor WebAssembly cenários de segurança adicionais
- Usar a API do Graph com o ASP.NET Core Blazor WebAssembly
- ASP.NET Core seguro Blazor WebAssembly
- Autorização baseada em declarações no ASP.NET Core Razor Pages
- Autorização baseada em declarações no MVC do ASP.NET Core
-
Estender ou adicionar declarações personalizadas, incluindo declarações de função, usando
IClaimsTransformation