Partilhar via


Autenticação e autorização do ASP.NET Core Blazor

Note

Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 10 deste artigo.

Warning

Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e do .NET Core. Para a versão atual, consulte a versão .NET 10 deste artigo.

Este artigo descreve o suporte do ASP.NET Core para a configuração e o gerenciamento de segurança em aplicativos Blazor.

Blazor usa os mecanismos de autenticação ASP.NET Core existentes para estabelecer a identidade do usuário. O mecanismo exato depende de como o aplicativo Blazor está hospedado, do lado do servidor ou do lado do cliente.

Os cenários de segurança diferem entre o código de autorização executado no lado do servidor e no lado do cliente em aplicativos Blazor. Para o código de autorização executado no servidor, as verificações de autorização podem impor regras de acesso para áreas do aplicativo e componentes. Como a execução de código do lado do cliente pode ser adulterada, não se pode confiar no código de autorização executado no cliente para impor absolutamente as regras de acesso ou controlar a exibição de conteúdo do lado do cliente.

Se a aplicação da regra de autorização precisar ser garantida, não implemente verificações de autorização no código do lado do cliente. Crie um Blazor Web App que confie unicamente na renderização do lado do servidor (SSR) para verificações de autorização e aplicação de regras.

Se a aplicação da regra de autorização e a segurança dos dados e do código precisarem ser garantidas, não desenvolva um aplicativo do lado do cliente. Crie um aplicativo Blazor Server.

Razor As convenções de autorização do Pages não se aplicam a componentes Razor navegáveis. Se um componente Razor não roteável estiver incorporado em uma página de um Razor aplicativo de Páginas, as convenções de autorização da página afetam indiretamente o Razor componente, juntamente com o restante do conteúdo da página.

ASP.NET Core Identity foi projetado para funcionar no contexto da comunicação de solicitação e resposta HTTP, que geralmente não é o modelo de comunicação cliente-servidor do aplicativo Blazor. Aplicações ASP.NET Core que utilizam o ASP.NET Core Identity para gestão de utilizadores devem usar Razor Páginas ao invés de componentes Razor para a interface do utilizador relacionada com Identity, como registo de utilizador, iniciar sessão, terminar sessão e outras tarefas de gestão de utilizadores. A criação de componentes Razor que lidam diretamente com Identity tarefas é possível para vários cenários, mas não é recomendada ou suportada pela Microsoft.

ASP.NET Abstrações principais, como SignInManager<TUser> e UserManager<TUser>, não são suportadas em componentes Razor. Para obter mais informações sobre como usar o ASP.NET Core Identity com Blazor, consulte Scaffold ASP.NET Core Identity num aplicativo Blazor do lado do servidor.

Note

Os exemplos de código neste artigo adotam tipos de referência anuláveis (NRTs) e análise estática de estado nulo do compilador .NET, que são suportados no ASP.NET Core no .NET 6 ou posterior. Ao direcionar para o .NET 5 ou versões anteriores, remova a designação de tipo nulo (?) dos exemplos neste artigo.

Mantenha dados e credenciais confidenciais com segurança

Não armazene segredos de aplicativos, cadeias de conexão, credenciais, senhas, números de identificação pessoal (PINs), código .NET/C# privado ou chaves/tokens privados no código do lado do cliente, que é sempre inseguro. O código Blazor do lado do cliente deve acessar serviços e bancos de dados seguros por meio de uma API da Web segura que você controla.

Em ambientes de teste/preparação e produção, o código Blazor do lado do servidor e as APIs da Web devem usar fluxos de autenticação seguros que evitem a manutenção de credenciais no código do projeto ou nos arquivos de configuração. Fora dos testes de desenvolvimento local, recomendamos evitar o uso de variáveis de ambiente para armazenar dados confidenciais, pois as variáveis de ambiente não são a abordagem mais segura. Para testes de desenvolvimento local, a ferramenta Secret Manager é recomendada para proteger dados confidenciais. Para obter mais informações, consulte os seguintes recursos:

Para desenvolvimento e testes locais do lado do cliente e do servidor, use a ferramenta Secret Manager para proteger credenciais confidenciais.

Identidades gerenciadas para serviços do Microsoft Azure

Para serviços do Microsoft Azure, recomendamos o uso de identidades gerenciadas . As identidades gerenciadas são autenticadas com segurança nos serviços do Azure sem armazenar credenciais no código do aplicativo. Para obter mais informações, consulte os seguintes recursos:

Suporte antifalsificação

O modelo Blazor:

O componente AntiforgeryToken renderiza um token antifalsificação como um campo oculto, e esse componente é adicionado automaticamente às instâncias de formulário (EditForm). Para obter mais informações, consulte Visão geral ASP.NET formulários principaisBlazor.

O serviço AntiforgeryStateProvider fornece acesso a um token antifalsificação associado à sessão atual. Injete o serviço e chame o seu método GetAntiforgeryToken() para obter o AntiforgeryRequestToken atual. Para mais informações, consulte Chamar uma API da Web a partir de uma aplicação ASP.NET Core Blazor.

Blazor armazena tokens de solicitação no estado do componente, o que garante que os tokens antifalsificação estejam disponíveis para componentes interativos, mesmo quando eles não têm acesso à solicitação.

Note

A mitigação antifalsificação só é necessária ao enviar dados de formulário para o servidor codificado como , application/x-www-form-urlencoded, ou multipart/form-data, uma vez que estes são os únicos enctypes text/plain.

Para obter mais informações, consulte os seguintes recursos:

Autenticação de Blazor do lado do servidor

Os aplicativos Blazor do lado do servidor são configurados para segurança da mesma maneira que os aplicativos ASP.NET Core. Para obter mais informações, consulte os artigos em tópicos de segurança do ASP.NET Core.

O contexto de autenticação só é estabelecido quando a aplicação começa, que é quando a aplicação se conecta pela primeira vez ao WebSocket por uma ligação com o cliente. A autenticação pode ser baseada em um cookie ou em algum outro token de portador, mas a autenticação é gerenciada através do hub SignalR e inteiramente dentro do circuito . O contexto de autenticação é mantido durante o tempo de vida do circuito. Os aplicativos revalidam periodicamente o estado de autenticação do usuário a cada 30 minutos.

Se a aplicação precisar capturar usuários para serviços personalizados ou reagir a atualizações do usuário, consulte ASP.NET Core do lado do servidor e Blazor Web App cenários adicionais de segurança.

Blazor difere dos aplicativos Web renderizados por servidor tradicionais que fazem novas solicitações HTTP com cookies em cada navegação de página. A autenticação é verificada durante eventos de navegação. No entanto, os cookies não estão envolvidos. Os cookies só são enviados quando se faz um pedido HTTP a um servidor, o que não acontece quando o utilizador navega numa aplicação Blazor. Durante a navegação, o estado de autenticação do usuário é verificado dentro do Blazor circuito, que pode ser atualizado a qualquer momento no servidor usando a RevalidatingAuthenticationStateProvider abstração.

Important

A implementação de um NavigationManager personalizado para obter a validação de autenticação durante a navegação não é recomendada. Se a aplicação precisar executar uma lógica personalizada de estado de autenticação durante a navegação, use um AuthenticationStateProviderpersonalizado.

Note

Os exemplos de código neste artigo adotam tipos de referência anuláveis (NRTs) e análise estática de estado nulo do compilador .NET, que são suportados no ASP.NET Core no .NET 6 ou posterior. Quando o alvo é .NET 5 ou anterior, remova a designação de tipo nulo (?) dos exemplos neste artigo.

O serviço de AuthenticationStateProvider interno ou personalizado obtém dados de estado de autenticação do HttpContext.User do ASP.NET Core. É assim que o estado de autenticação se integra aos mecanismos de autenticação ASP.NET Core existentes.

Estado compartilhado

Os aplicativos Blazor do lado do servidor vivem na memória do servidor e várias sessões de aplicativos são hospedadas no mesmo processo. Para cada sessão de aplicativo, Blazor inicia um circuito com um escopo próprio de contêiner de injeção de dependências, portanto, os serviços de escopo são exclusivos por sessão de Blazor.

Warning

Não recomendamos que aplicações no mesmo servidor partilhem estado usando serviços singleton, a menos que seja tomado extremo cuidado, pois isso pode introduzir vulnerabilidades de segurança, como a divulgação do estado do utilizador entre circuitos.

Você pode usar serviços singleton com estado em aplicações Blazor se forem projetados especificamente para isso. Por exemplo, o uso de um cache de memória singleton é aceitável porque um cache de memória requer uma chave para acessar uma determinada entrada. Supondo que os usuários não tenham controle sobre as chaves de cache usadas com o cache, o estado armazenado no cache não vaza entre circuitos.

Para obter orientações gerais sobre o gerenciamento de estado, consulte ASP.NET Visão geral do gerenciamento de estado principalBlazor.

Segurança do lado do servidor de dados e credenciais confidenciais

Em ambientes de teste/preparação e produção, o código Blazor do lado do servidor e as APIs da Web devem usar fluxos de autenticação seguros que evitem a manutenção de credenciais no código do projeto ou nos arquivos de configuração. Fora dos testes de desenvolvimento local, recomendamos evitar o uso de variáveis de ambiente para armazenar dados confidenciais, pois as variáveis de ambiente não são a abordagem mais segura. Para testes de desenvolvimento local, a ferramenta Secret Manager é recomendada para proteger dados confidenciais. Para obter mais informações, consulte os seguintes recursos:

Para desenvolvimento e testes locais do lado do cliente e do servidor, use a ferramenta Secret Manager para proteger credenciais confidenciais.

Modelo de projeto

Crie um novo aplicativo do lado Blazor do servidor seguindo as orientações em Ferramentas para ASP.NET Core Blazor.

Depois de escolher o modelo de aplicativo do lado do servidor e configurar o projeto, selecione a autenticação do aplicativo em Tipo de autenticação:

  • Nenhum (padrão): Sem autenticação.
  • Contas individuais: as contas de usuário são armazenadas no aplicativo usando ASP.NET Core Identity.
  • Nenhum (padrão): Sem autenticação.
  • Contas individuais: as contas de usuário são armazenadas no aplicativo usando ASP.NET Core Identity.
  • Plataforma de identidade da Microsoft: Para obter mais informações, consulte os links na seção Recursos adicionais .
  • Windows: Use a Autenticação do Windows.

Blazor Identity UI (Contas Individuais)

Quando se escolhe a opção de autenticação para Blazor, Blazor suporta a geração de uma interface do usuário completa baseada em Identity.

O modelo Blazor Web App serve de estrutura para o código Identity de um banco de dados de SQL Server. A versão de linha de comando usa SQLite e inclui um banco de dados SQLite para Identity.

O modelo:

  • Suporta cenários interativos de renderização do lado do servidor (SSR interativo) e CSR (renderização do lado do cliente) com usuários autenticados.
  • Adiciona IdentityRazor componentes e lógica relacionada para tarefas de autenticação de rotina, como entrar e sair de usuários. Os Identity componentes também suportam recursos avançados Identity , como confirmação de conta e recuperação de senha e autenticação multifator usando um aplicativo de terceiros. Observe que os próprios componentes Identity não suportam interatividade.
  • Adiciona os pacotes e dependências relacionados ao Identity.
  • Faz referência aos pacotes Identity em _Imports.razor.
  • Cria uma classe de usuário Identity personalizada (ApplicationUser).
  • Cria e registra um contexto de banco de dados EF Core (ApplicationDbContext).
  • Configura o roteamento para as extremidades integradas de Identity.
  • Inclui validação Identity e lógica de negócios.

Para inspecionar os componentes da estrutura do , aceda-os nas pastas e da pasta no projeto de servidor do modelo de projeto ( repositório GitHub).

Quando você escolhe os modos de renderização Interactive WebAssembly ou Interactive Auto, o servidor lida com todas as solicitações de autenticação e autorização, e os componentes Identity renderizam estaticamente no servidor no projeto principal do Blazor Web App.

O framework fornece uma AuthenticationStateProvider personalizada nos projetos de servidor e cliente (.Client) de modo a transmitir o estado de autenticação do utilizador para o navegador. O projeto de servidor chama AddAuthenticationStateSerialization, enquanto o projeto cliente chama AddAuthenticationStateDeserialization. A autenticação no servidor em vez do cliente permite que o aplicativo acesse o estado de autenticação durante a pré-renderização e antes que o tempo de execução do .NET WebAssembly seja inicializado. As implementações personalizadas de AuthenticationStateProvider usam o serviço de Estado de Componente Persistente (PersistentComponentState) para serializar o estado de autenticação em comentários HTML e para depois lê-lo de volta do WebAssembly, criando assim uma nova instância de AuthenticationState. Para obter mais informações, consulte a seção Gerenciar estado de autenticação em Blazor Web Apps .

Somente para soluções de Servidor Interativo, IdentityRevalidatingAuthenticationStateProvider (Components/Account/IdentityRevalidatingAuthenticationStateProvider.cs) no projeto de servidor do modelo de projeto Blazor Web App (dotnet/aspnetcore repositório GitHub) é um componente do lado do servidor AuthenticationStateProvider que revalida o carimbo de segurança para o usuário conectado a cada 30 minutos enquanto o circuito interativo está conectado.

Quando você escolhe os modos de renderização Interactive WebAssembly ou Interactive Auto, o servidor lida com todas as solicitações de autenticação e autorização, e os componentes Identity renderizam estaticamente no servidor no projeto principal do Blazor Web App. O modelo de projeto inclui uma classe (fonte de referência) no projeto para sincronizar o estado de autenticação do utilizador entre o servidor e o navegador. A classe é uma implementação personalizada de AuthenticationStateProvider. O provedor usa o serviço de Estado Persistente do Componente (PersistentComponentState) para pré-renderizar o estado de autenticação e preservá-lo na página.

No projeto principal de um Blazor Web App, o provedor de estado de autenticação é nomeado IdentityRevalidatingAuthenticationStateProvider no diretório Components/Account do projeto de servidor no modelo de projeto Blazor Web App (dotnet/aspnetcore repositório GitHub) (aplicável apenas a soluções de interatividade do servidor) ou como PersistingRevalidatingAuthenticationStateProvider para soluções de interatividade WebAssembly ou Automática, no mesmo diretório.

Blazor Identity depende de DbContext instâncias não criadas por uma fábrica, o que é intencional porque DbContext é suficiente para que os Identity componentes do modelo de projeto sejam renderizados estaticamente sem oferecer suporte à interatividade.

Para obter uma descrição sobre como os modos de renderização interativos globais são aplicados a componentes nãoIdentity e, ao mesmo tempo, impõem SSR estático para os componentes Identity, consulte modos de renderização do ASP.NET Core Blazor.

Para obter mais informações sobre a persistência do estado pré-renderizado, consulte ASP.NET Persistência Blazor do estado pré-renderizado do núcleo.

Note

Os links de documentação para a fonte de referência do .NET geralmente carregam a ramificação padrão do repositório, que representa o desenvolvimento atual para a próxima versão do .NET. Para selecionar uma etiqueta para uma versão específica, use a lista suspensa Mudar ramificações ou etiquetas. Para obter mais informações, consulte Como selecionar uma marca de versão do código-fonte ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Gerenciar o estado de autenticação no Blazor Web Apps

Esta secção aplica-se aos Blazor Web Appque adotam:

  • Contas individuais
  • Renderização do lado do cliente (CSR, interatividade suportada por WebAssembly).

Um provedor de estado de autenticação do lado do cliente é usado apenas dentro do Blazor e não está integrado ao sistema de autenticação ASP.NET Core. Durante a pré-renderização, Blazor respeita os metadados definidos na página e usa o sistema de autenticação ASP.NET Core para determinar se o usuário está autenticado. Quando um usuário navega de uma página para outra, um provedor de autenticação do lado do cliente é usado. Quando o usuário atualiza a página (recarga de página inteira), o provedor de estado de autenticação do lado do cliente não está envolvido na decisão de autenticação no servidor. Como o estado do usuário não é persistido pelo servidor, qualquer estado de autenticação mantido no lado do cliente é perdido.

Para resolver isso, a melhor abordagem é executar a autenticação dentro do sistema de autenticação ASP.NET Core. O provedor de estado de autenticação do lado do cliente cuida apenas de refletir o estado de autenticação do usuário. Exemplos de como fazer isso com provedores de estado de autenticação são demonstrados pelo modelo de projeto Blazor Web App e descritos abaixo.

No ficheiro do projeto de servidor, chame , que serializa o retornado pelo do lado do servidor utilizando o serviço de Estado Persistente do Componente ():

builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents()
    .AddAuthenticationStateSerialization();

A API serializa apenas o nome do lado do servidor e as declarações de função para acesso no navegador. Para incluir todas as declarações, defina SerializeAllClaims como true na chamada do lado do servidor para AddAuthenticationStateSerialization:

builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents()
    .AddAuthenticationStateSerialization(
        options => options.SerializeAllClaims = true);

No arquivo .Client do projeto cliente (Program), chame AddAuthenticationStateDeserialization, que adiciona um AuthenticationStateProvider onde o AuthenticationState é desserializado do servidor usando AuthenticationStateData e o serviço de Estado de Componente Persistente (PersistentComponentState). Deve haver uma chamada correspondente para AddAuthenticationStateSerialization no projeto de servidor.

builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthenticationStateDeserialization();

Note

Os links de documentação para a fonte de referência do .NET geralmente carregam a ramificação padrão do repositório, que representa o desenvolvimento atual para a próxima versão do .NET. Para selecionar uma etiqueta para uma versão específica, use a lista suspensa Mudar ramificações ou etiquetas. Para obter mais informações, consulte Como selecionar uma marca de versão do código-fonte ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Andaime Identity

Para obter mais informações sobre scaffolding Identity num aplicativo do lado do servidor Blazor, consulte Scaffolding Identity em projetos ASP.NET Core.

Scaffold Identity num aplicativo Blazor do lado do servidor:

Reivindicações e tokens adicionais de fornecedores externos

Para armazenar adicionais declarações de provedores externos, consulte Como persistir declarações e tokens adicionais de provedores externos no ASP.NET Core.

Serviço de Aplicativo do Azure no Linux com Identity Server

Especifique o emissor explicitamente ao implementar no App Service do Azure no Linux com o Servidor Identity. Para obter mais informações, consulte Utilizar Identity para proteger um backend de API da Web para SPAs.

Injetar AuthenticationStateProvider para serviços com escopo de um componente

Não tente resolver AuthenticationStateProvider dentro de um escopo personalizado porque isso resulta na criação de uma nova instância do AuthenticationStateProvider que não foi inicializada corretamente.

Para aceder ao AuthenticationStateProvider dentro de um serviço com âmbito para um componente, injete o AuthenticationStateProvider no componente e passe-o para o serviço como um parâmetro. Essa abordagem garante que a instância correta e inicializada do AuthenticationStateProvider seja usada para cada instância do aplicativo do usuário.

ExampleService.cs:

public class ExampleService
{
    public async Task<string> ExampleMethod(AuthenticationStateProvider authStateProvider)
    {
        var authState = await authStateProvider.GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            return $"{user.Identity.Name} is authenticated.";
        }
        else
        {
            return "The user is NOT authenticated.";
        }
    }
}

Registe o serviço com escopo definido. Em uma aplicação Blazor do lado do servidor, os serviços com escopo têm um tempo de vida igual à duração do circuito de conexão do cliente .

No ficheiro Program:

builder.Services.AddScoped<ExampleService>();

Em Startup.ConfigureServices de Startup.cs:

services.AddScoped<ExampleService>();

No seguinte componente InjectAuthStateProvider:

InjectAuthStateProvider.razor:

@page "/inject-auth-state-provider"
@inherits OwningComponentBase
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>Inject <code>AuthenticationStateProvider</code> Example</h1>

<p>@message</p>

@code {
    private string? message;
    private ExampleService? ExampleService { get; set; }

    protected override async Task OnInitializedAsync()
    {
        ExampleService = ScopedServices.GetRequiredService<ExampleService>();

        message = await ExampleService.ExampleMethod(AuthenticationStateProvider);
    }
}
@page "/inject-auth-state-provider"
@inject AuthenticationStateProvider AuthenticationStateProvider
@inherits OwningComponentBase

<h1>Inject <code>AuthenticationStateProvider</code> Example</h1>

<p>@message</p>

@code {
    private string? message;
    private ExampleService? ExampleService { get; set; }

    protected override async Task OnInitializedAsync()
    {
        ExampleService = ScopedServices.GetRequiredService<ExampleService>();

        message = await ExampleService.ExampleMethod(AuthenticationStateProvider);
    }
}

Para obter mais informações, consulte as orientações sobre OwningComponentBase em injeção de dependência do ASP.NET Core Blazor.

Exibição de conteúdo não autorizado durante a pré-renderização com um AuthenticationStateProvider personalizado

Para evitar mostrar conteúdo não autorizado, por exemplo, conteúdo num AuthorizeView componente, durante a pré-renderização com um AuthenticationStateProvider personalizado, adote uma das seguintes abordagens:

  • Desativar pré-renderização: indique o modo de renderização com o parâmetro prerender definido como false no componente de nível mais alto na hierarquia de componentes do aplicativo que não seja um componente raiz.

    Note

    Não há suporte para tornar um componente raiz interativo, como o componente App. Portanto, a pré-renderização não pode ser desabilitada diretamente pelo componente App.

    Para aplicativos baseados no modelo de projeto Blazor Web App, a pré-renderização normalmente é desabilitada quando o componente Routes é usado no componente App (Components/App.razor) :

    <Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
    

    Além disso, desative a pré-renderização para o componente HeadOutlet:

    <HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />
    

    Você também pode controlar seletivamente o modo de renderização aplicado à instância do componente Routes. Por exemplo, consulte os modos de renderização do ASP.NET Core Blazor.

  • Desativar a pré-renderização: abra o _Host.cshtml arquivo e altere o render-mode atributo do Component Tag Helper para Server:

    <component type="typeof(App)" render-mode="Server" />
    
  • Autenticar o utilizador no servidor antes de a aplicação ser iniciada: para adotar esta abordagem, a aplicação deve responder à solicitação inicial de um utilizador com a página ou a vista de início de sessão baseada em Identitye impedir quaisquer solicitações para pontos de extremidade Blazor até que sejam autenticados. Para obter mais informações, consulte Criar um aplicativo ASP.NET Core com dados do usuário protegidos por autorização. Após a autenticação, o conteúdo não autorizado em componentes Razor pré-renderizados só é mostrado quando o usuário está realmente não autorizado a visualizar o conteúdo.

Gerenciamento de estado do usuário

Apesar da palavra "estado" no nome, AuthenticationStateProvider não é para armazenar o estado geral do usuário. AuthenticationStateProvider indica apenas o estado de autenticação do usuário para o aplicativo, se ele está conectado ao aplicativo e com quem está conectado.

A autenticação usa a mesma autenticação ASP.NET Core Identity que os aplicativos Razor Pages e MVC. O estado do usuário armazenado para ASP.NET Core Identity flui para Blazor sem adicionar código adicional ao aplicativo. Siga as orientações nos artigos e tutoriais do ASP.NET Core Identity para que os recursos de Identity entrem em vigor nas partes Blazor do aplicativo.

Para obter orientações sobre o gerenciamento geral do estado fora do ASP.NET CoreIdentity, consulte ASP.NET Visão geral do gerenciamento do estado principalBlazor.

Abstrações de segurança adicionais

Duas abstrações adicionais participam do gerenciamento do estado de autenticação:

Note

Os links de documentação para a fonte de referência do .NET geralmente carregam a ramificação padrão do repositório, que representa o desenvolvimento atual para a próxima versão do .NET. Para selecionar uma etiqueta para uma versão específica, use a lista suspensa Mudar ramificações ou etiquetas. Para obter mais informações, consulte Como selecionar uma marca de versão do código-fonte ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Em aplicativos gerados a partir do Blazor modelo de projeto para .NET 8 ou posterior, ajuste o intervalo de revalidação padrão de 30 minutos em IdentityRevalidatingAuthenticationStateProvider. Antes do .NET 8, ajuste o intervalo em RevalidatingIdentityAuthenticationStateProvider. O exemplo a seguir reduz o intervalo para 20 minutos:

protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(20);

Gestão do estado de autenticação ao terminar sessão

O Blazor do lado do servidor persiste o estado de autenticação do utilizador durante o tempo de vida do circuito, incluindo entre as abas do navegador. Para desconectar proativamente um utilizador nas guias do navegador quando o utilizador sair de uma guia, deve implementar um RevalidatingServerAuthenticationStateProvider (fonte de referência) com um RevalidationIntervalcurto.

Note

Os links de documentação para a fonte de referência do .NET geralmente carregam a ramificação padrão do repositório, que representa o desenvolvimento atual para a próxima versão do .NET. Para selecionar uma etiqueta para uma versão específica, use a lista suspensa Mudar ramificações ou etiquetas. Para obter mais informações, consulte Como selecionar uma marca de versão do código-fonte ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Duração da validade do URL de redirecionamento temporário

Esta secção aplica-se a Blazor Web Apps.

Use a opção RazorComponentsServiceOptions.TemporaryRedirectionUrlValidityDuration para obter ou definir o tempo de vida da validade do ASP.NET Core Data Protection para URLs de redirecionamento temporário emitidas pela renderização do lado do servidor Blazor. Eles são usados apenas transitoriamente, então o tempo de vida só precisa ser longo o suficiente para que um cliente receba a URL e comece a navegação para ela. No entanto, ele também deve ser longo o suficiente para permitir o desvio do relógio entre servidores. O valor padrão é cinco minutos.

No exemplo a seguir, o valor é estendido para sete minutos:

builder.Services.AddRazorComponents(options => 
    options.TemporaryRedirectionUrlValidityDuration = 
        TimeSpan.FromMinutes(7));

Autenticação Blazor do lado do cliente

Nos aplicativos do cliente de Blazor, as verificações de autenticação no cliente podem ser ignoradas porque todo o código do cliente pode ser modificado pelos utilizadores. O mesmo vale para todas as tecnologias de aplicativos do lado do cliente, incluindo estruturas de SPA JavaScript e aplicativos nativos para qualquer sistema operacional.

Aditar o seguinte:

Para lidar com a autenticação, use o serviço de AuthenticationStateProvider interno ou personalizado.

Para obter mais informações sobre a autenticação do lado do cliente, consulte Secure ASP.NET Core Blazor WebAssembly.

Proteja os dados em Blazor Web App com renderização interativa automática

Quando um Blazor Web App adota a renderização do lado do servidor (SSR) e a renderização do lado do cliente (CSR) para componentes ou um aplicativo inteiro que especifica o modo de renderização automática interativa, a autorização para acessar componentes e dados é aplicada em dois locais. O componente restringe o acesso a si mesmo (e a quaisquer dados que obtenha) quando processado no servidor em virtude de um atributo de autorização no arquivo de definição do componente (@attribute [Authorize]). Quando o componente é renderizado no cliente, o acesso aos dados é restrito através dos endpoints da API web do servidor chamados do cliente. Deve-se ter cuidado ao proteger o acesso aos dados em ambos os locais para evitar o acesso indevido aos dados.

Considere o seguinte cenário em que dados meteorológicos seguros são exibidos por um componente. Demonstrações de algumas das seguintes abordagens podem ser avaliadas e testadas usando os BlazorWebAppEntra/BlazorWebAppEntraBffexemplos (.NET 9 ou posterior) ou osBlazorWebAppOidc/BlazorWebAppOidcBffexemplos (.NET 8 ou posterior) no Blazor repositório GitHub de exemplos (dotnet/blazor-samples) (como baixar).

O projeto cliente mantém uma classe WeatherForecast para armazenar dados meteorológicos:

public sealed class WeatherForecast(DateOnly date, int temperatureC, string summary)
{
    public DateOnly Date { get; set; } = date;
    public int TemperatureC { get; set; } = temperatureC;
    public string? Summary { get; set; } = summary;
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

A interface IWeatherForecaster do projeto cliente define um método GetWeatherForecastAsync para obter dados meteorológicos:

public interface IWeatherForecaster
{
    Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync();
}

O serviço de ClientWeatherForecaster do projeto cliente implementa IWeatherForecaster. O método GetWeatherForecastAsync chama uma API web no projeto do servidor no endpoint /weather-forecast para dados meteorológicos:

internal sealed class ClientWeatherForecaster(HttpClient httpClient) 
    : IWeatherForecaster
{
    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync() =>
        await httpClient.GetFromJsonAsync<WeatherForecast[]>("/weather-forecast") ??
            throw new IOException("No weather forecast!");
}

O projeto cliente mantém um componente Weather que:

@page "/weather"
@using Microsoft.AspNetCore.Authorization
@using BlazorWebAppEntra.Client.Weather
@attribute [Authorize]
@inject IWeatherForecaster WeatherForecaster

<PageTitle>Weather</PageTitle>

<h1>Weather</h1>

<p>This component demonstrates showing data.</p>

@if (Forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th aria-label="Temperature in Celsius">Temp. (C)</th>
                <th aria-label="Temperature in Fahrenheit">Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in Forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    [PersistentState]
    public IEnumerable<WeatherForecast>? Forecasts { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Forecasts ??= await WeatherForecaster.GetWeatherForecastAsync();
    }
}
@page "/weather"
@using Microsoft.AspNetCore.Authorization
@using BlazorWebAppEntra.Client.Weather
@attribute [Authorize]
@implements IDisposable
@inject PersistentComponentState ApplicationState
@inject IWeatherForecaster WeatherForecaster

<PageTitle>Weather</PageTitle>

<h1>Weather</h1>

<p>This component demonstrates showing data.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th aria-label="Temperature in Celsius">Temp. (C)</th>
                <th aria-label="Temperature in Fahrenheit">Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private IEnumerable<WeatherForecast>? forecasts;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        if (!ApplicationState.TryTakeFromJson<IEnumerable<WeatherForecast>>(
            nameof(forecasts), out var restoredData))
        {
            forecasts = await WeatherForecaster.GetWeatherForecastAsync();
        }
        else
        {
            forecasts = restoredData!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson(nameof(forecasts), forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose() => persistingSubscription.Dispose();
}

O projeto de servidor implementa IWeatherForecaster como ServerWeatherForecaster, o que gera e retorna dados meteorológicos através do seu método GetWeatherForecastAsync.

internal sealed class ServerWeatherForecaster() : IWeatherForecaster
{
    public readonly string[] summaries =
    [
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", 
        "Sweltering", "Scorching"
    ];

    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
    {
        // Simulate asynchronous loading to demonstrate streaming rendering
        await Task.Delay(500);

        return Enumerable.Range(1, 5).Select(index =>
            new WeatherForecast
            (
                DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                Random.Shared.Next(-20, 55),
                summaries[Random.Shared.Next(summaries.Length)]
            ))
        .ToArray();
    }
}

Se o aplicativo precisar chamar uma API da Web externa para obter os dados meteorológicos, você poderá injetar um cliente HTTP (HttpClient) para solicitar os dados:

internal sealed class ServerWeatherForecaster(HttpClient httpClient, 
    IHttpContextAccessor httpContextAccessor) : IWeatherForecaster
{
    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
    {
        var httpContext = httpContextAccessor.HttpContext ??
            throw new InvalidOperationException("No HttpContext!");
        var accessToken = await httpContext.GetTokenAsync("access_token") ??
            throw new InvalidOperationException("No access_token was saved");
        using var request = 
            new HttpRequestMessage(HttpMethod.Get, "/weather-forecast");
        request.Headers.Authorization = new("Bearer", accessToken);
        using var response = await httpClient.SendAsync(request);
        response.EnsureSuccessStatusCode();

        return await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ??
            throw new IOException("No weather forecast!");
    }
}

Em outra abordagem, pode-se injetar uma fábrica de clientes HTTP (IHttpClientFactory) no ServerWeatherForecaster e chamar uma API da Web externa usando um cliente HTTP nomeado com um manipulador de token. Para mais informações, consulte Chamar uma API da Web a partir de uma aplicação ASP.NET Core Blazor.

Se o aplicativo usa a plataforma de identidade da Microsoft com pacotes da Web da Microsoft Identity para oMicrosoft Entra ID (consulte Chamar uma API da Web de um aplicativo ASP.NET CoreBlazor), o seguinte ServerWeatherForecaster demonstra como fazer uma chamada de API da Web externa. O token de acesso é automaticamente anexado à solicitação.

internal sealed class ServerWeatherForecaster(IDownstreamApi downstreamApi) : IWeatherForecaster
{
    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
    {
        using var response = await downstreamApi.CallApiForUserAsync("DownstreamApi",
            options =>
            {
                options.RelativePath = "/weather-forecast";
            });

        return await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ??
            throw new IOException("No weather forecast!");
    }
}

Independentemente da abordagem adotada pelo ServerWeatherForecaster para obter os dados, o projeto de servidor mantém um ponto de extremidade de API da Web seguro para chamadas de dados meteorológicos do cliente. Este endpoint resulta em uma ServerWeatherForecaster.GetWeatherForecastAsync invocação no servidor.

app.MapGet("/weather-forecast", (
    [FromServices] IWeatherForecaster WeatherForecaster) =>
{
    return WeatherForecaster.GetWeatherForecastAsync();
}).RequireAuthorization();

Usando a abordagem anterior, existem dois sistemas para fornecer dados meteorológicos seguros ao usuário:

  • Quando o Weather componente é renderizado no servidor, o ServerWeatherForecaster método do GetWeatherForecastAsync serviço é usado diretamente para obter os dados meteorológicos. A segurança dos dados é garantida pelo atributo do componente . Em resumo, a segurança dos dados meteorológicos é imposta pelo componente.
  • Quando o componente Weather é renderizado nodo cliente, o serviço ClientWeatherForecaster é usado para fazer uma chamada à API da Web para o ponto de extremidade seguro /weather-forecast que aplica o método de extensão RequireAuthorization. Se o utilizador tiver autorização para aceder aos dados meteorológicos, o ponto de extremidade usa o serviço ServerWeatherForecaster para ligar para GetWeatherForecastAsync. Os dados são devolvidos ao cliente. O servidor garante a segurança dos dados meteorológicos através do uso do endpoint da sua API web.

A abordagem anterior funciona bem quando os requisitos de segurança da API da Web correspondem aos requisitos de segurança do componente. Por exemplo, a mesma política de autorização pode ser aplicada ao ponto de extremidade da API da Web e ao componente.

Cenários complexos exigem planejamento e implementação adicionais. Por exemplo, uma API Web de servidor que tenha vários chamadores com permissões de acesso diferentes requer uma política de autorização mais sofisticada, uma ou mais políticas adicionais ou pontos de extremidade adicionais com requisitos de acesso diferentes.

Ao integrar segurança nos aplicativos que adotam renderização automática interativa, lembre-se de que a segurança implementada para os pontos de extremidade da API Web do servidor não protege a implementação do serviço do servidor usada quando um componente é renderizado no servidor e acessa dados através do serviço. Pese cuidadosamente a diferença entre acessar dados no servidor durante o SSR versus acessar os dados em uma solicitação de API da Web do cliente durante o CSR. Aplique estrategicamente a segurança para evitar o acesso indevido aos dados.

Exemplos no repositório do GitHub Blazor (dotnet/blazor-samples) (como fazer download) que demonstram a abordagem descrita nesta seção:

  • BlazorWebAppOidc
  • BlazorWebAppOidcBff
  • BlazorWebAppEntra
  • BlazorWebAppEntraBff

AuthenticationStateProvider serviço

AuthenticationStateProvider é o serviço subjacente usado pelo componente AuthorizeView e serviços de autenticação em cascata para obter o estado de autenticação para um usuário.

AuthenticationStateProvider é o serviço subjacente usado pelo componente AuthorizeView e pelo componente CascadingAuthenticationState para obter o estado de autenticação de um usuário.

Normalmente, você não usa AuthenticationStateProvider diretamente. Use o componente AuthorizeView ou as abordagens Task<AuthenticationState> descritas posteriormente neste artigo. A principal desvantagem de usar AuthenticationStateProvider diretamente é que o componente não é notificado automaticamente se os dados do estado de autenticação subjacente forem alterados.

Para implementar um AuthenticationStateProvider personalizado, consulte ASP.NET Core Blazor de estado de autenticação, que inclui orientações sobre como implementar notificações de alteração do estado de autenticação do utilizador.

Obter os dados principais de declarações de um usuário

O serviço AuthenticationStateProvider pode fornecer os dados de ClaimsPrincipal do usuário atual, conforme mostrado no exemplo a seguir.

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.";
        }
    }
}

No exemplo anterior:

  • ClaimsPrincipal.Claims retorna as declarações do usuário (claims) para exibição na interface do usuário.
  • A linha que obtém o sobrenome do usuário (surname) chama ClaimsPrincipal.FindAll com um predicado para filtrar as declarações do usuário.
@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.";
        }
    }
}

Se user.Identity.IsAuthenticated for true e porque o usuário é um ClaimsPrincipal, as declarações podem ser enumeradas e a associação em funções avaliada.

Para obter mais informações sobre injeção de dependência (DI) e serviços, consulte injeção de dependência do ASP.NET Core Blazor e Injeção de dependência no ASP.NET Core. Para obter informações sobre como implementar um AuthenticationStateProvider personalizado, consulte o estado de autenticação no ASP.NET CoreBlazor.

Expor o estado de autenticação como um parâmetro em cascata

Se os dados do estado de autenticação forem necessários para a lógica processual, como ao executar uma ação acionada pelo usuário, obtenha os dados do estado de autenticação definindo um parâmetro em cascata do tipo Task<AuthenticationState>, como demonstra o exemplo a seguir.

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.";
            }
        }
    }
}

Se user.Identity.IsAuthenticated for true, as afirmações podem ser enumeradas e a participação em funções ser avaliada.

Configure o parâmetro em cascata Task<AuthenticationState> usando os serviços de autenticação em cascata e de estado AuthorizeRouteView.

Quando você cria um aplicativo Blazor a partir de um dos modelos de projeto Blazor com a autenticação habilitada, o aplicativo inclui o AuthorizeRouteView e a chamada para AddCascadingAuthenticationState mostrados no exemplo a seguir. Uma aplicação Blazor no lado cliente também inclui os registos de serviço necessários. Informações adicionais são apresentadas na seção Personalizar o conteúdo não autorizado com o componente Router.

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

No arquivo Program, registre os serviços de estado de autenticação em cascata:

builder.Services.AddCascadingAuthenticationState();

Configure o parâmetro em cascata Task<AuthenticationState> usando os componentes AuthorizeRouteView e CascadingAuthenticationState.

Quando você cria um aplicativo Blazor a partir de um dos Blazor modelos de projeto com a autenticação habilitada, o aplicativo inclui os componentes AuthorizeRouteView e CascadingAuthenticationState mostrados no exemplo a seguir. Uma aplicação Blazor no lado cliente também inclui os registos de serviço necessários. Informações adicionais são apresentadas na seção Personalizar o conteúdo não autorizado com o componente Router.

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

Note

Com o lançamento do .NET 5.0.1 e para quaisquer versões adicionais do 5.x, o Router componente inclui o PreferExactMatches parâmetro definido como @true. Para obter mais informações, consulte Migrar do ASP.NET Core 3.1 para o .NET 5.

Num aplicativo cliente Blazor, adicione serviços de autorização ao ficheiro Program:

builder.Services.AddAuthorizationCore();

Num app Blazor do lado do cliente, adicione opções assim como serviços de autorização ao ficheiro Program.

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

Em um aplicativo de Blazor do lado do servidor, os serviços de opções e autorização já estão presentes, portanto, nenhuma etapa adicional é necessária.

Authorization

Depois que um usuário é autenticado, as regras de autorização são aplicadas para controlar o que o usuário pode fazer.

Normalmente, o acesso é concedido ou negado com base no seguinte:

  • Um usuário é autenticado (conectado).
  • Um utilizador está numa função .
  • Um utilizador tem uma reivindicação .
  • Uma política é satisfeita.

Cada um desses conceitos é o mesmo que em um aplicativo ASP.NET Core MVC ou Razor Pages. Para obter mais informações sobre a segurança ASP.NET Core, consulte os artigos em ASP.NET Core Security e Identity.

componente AuthorizeView

O componente AuthorizeView exibe seletivamente o conteúdo da interface do usuário, dependendo se o usuário está autorizado. Essa abordagem é útil quando você só precisa exibir dados para o usuário e não precisa usar a identidade do usuário na lógica processual.

O componente expõe uma variável context do tipo AuthenticationState (@context na sintaxe Razor), que você pode usar para acessar informações sobre o usuário conectado:

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

Você também pode fornecer conteúdo diferente para exibição se o usuário não estiver autorizado com uma combinação dos parâmetros Authorized e 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() { ... }
}

Embora o componente AuthorizeView controle a visibilidade dos elementos com base no status de autorização do usuário, ele não impõe segurança no próprio manipulador de eventos. No exemplo anterior, o método HandleClick é associado apenas a um botão visível para usuários autorizados, mas nada impede que esse método seja invocado de outros lugares. Para garantir a segurança no nível do método, implemente uma lógica de autorização adicional no próprio manipulador ou na API relevante.

Razor componentes do Blazor Web Appnunca exibem conteúdo <NotAuthorized> quando a autorização falha durante a renderização estática no servidor (SSR estático). O pipeline do ASP.NET Core do lado do servidor processa a autorização no servidor. Use técnicas do lado do servidor, como configurar LoginPath para lidar com pedidos não autorizados. Para obter mais informações, consulte modos de renderização do ASP.NET Core Blazor.

Warning

Os elementos de marcação e os métodos do lado do cliente associados a um AuthorizeView só são protegidos contra exibição e execução na interface do usuário renderizada em aplicativos do lado do cliente Blazor. Para proteger o conteúdo autorizado e métodos seguros no Blazordo lado do cliente, o conteúdo geralmente é fornecido por uma chamada de API da Web segura e autorizada para uma API de servidor e nunca é armazenado no aplicativo. Para obter mais informações, consulte Chamar uma API da Web de uma aplicação ASP.NET Core Blazor e cenários de segurança adicionais do ASP.NET CoreBlazor WebAssembly.

O conteúdo de Authorized e NotAuthorized pode incluir itens arbitrários, como outros componentes interativos.

As condições de autorização, como funções ou políticas que controlam as opções ou o acesso da interface do usuário, são abordadas na seção de autorização.

Se as condições de autorização não forem especificadas, AuthorizeView usará uma política padrão:

  • Os usuários autenticados (conectados) são autorizados.
  • Os usuários não autenticados (desconectados) não são autorizados.

O componente AuthorizeView pode ser usado no componente NavMenu (Shared/NavMenu.razor) para exibir o componente NavLink (NavLink), mas observe que este método remove apenas o item de lista da saída renderizada. Isso não impede que o usuário navegue até o componente. Implemente a autorização separadamente no componente de destino.

Autorização baseada em funções e políticas

O componente oferece suporte a autorização baseada em função ou autorização baseada em política .

Para autorização baseada em função, use o parâmetro Roles. No exemplo a seguir, o usuário deve ter uma declaração de função para as funções Admin ou Superuser:

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

Para exigir que um utilizador tenha declarações de função Admin e Superuser, aninhe os componentes 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>

O código anterior define um Context para o componente interno AuthorizeView, de forma a evitar uma colisão no contexto AuthenticationState. O contexto AuthenticationState é acedido na AuthorizeView externa com o método padrão para aceder ao contexto (@context.User). O contexto na AuthorizeView interna é acessado com o contexto nomeado innerContext (@innerContext.User).

Para obter mais informações, incluindo diretrizes de configuração, consulte Autorização baseada em função no ASP.NET Core.

Para autorização baseada em política, use o parâmetro Policy com um único nome de política:

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

Para lidar com o caso em que o usuário deve satisfazer uma das várias políticas, crie uma política que confirme que o usuário satisfaz outras políticas.

Para lidar com o caso em que o usuário deve satisfazer várias políticas simultaneamente, execute uma das seguintes abordagens:

  • Crie uma política para AuthorizeView que confirme que o usuário satisfaz várias outras políticas.

  • Incorporar as políticas em vários componentes AuthorizeView:

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

A autorização baseada em declarações é um caso especial de autorização baseada em políticas. Por exemplo, você pode definir uma política que exija que os usuários tenham uma determinada declaração. Para obter mais informações, consulte Autorização baseada em políticas no ASP.NET Core.

Se tanto Roles como Policy forem definidos, a autorização só será bem-sucedida quando ambas as condições forem satisfeitas. Ou seja, o usuário deve pertencer a pelo menos uma das funções especificadas e atender aos requisitos definidos pela política.

Se nem Roles nem Policy for especificado, AuthorizeView usará a política padrão:

  • Os usuários autenticados (conectados) são autorizados.
  • Os usuários não autenticados (desconectados) não são autorizados.

Como as strings .NET são sensíveis a maiúsculas e minúsculas, a correspondência de nomes de função e política também é sensível a maiúsculas e minúsculas. Por exemplo, Admin (em maiúsculas A) não é considerado o mesmo papel que admin (em minúsculas a).

O caso Pascal é normalmente usado para nomes de funções e políticas (por exemplo, BillingAdministrator), mas o uso do caso Pascal não é um requisito estrito. Diferentes esquemas de invólucro, como caixa de camelo, caixa de kebab e caixa de cobra, são permitidos. O uso de espaços em nomes de funções e políticas é incomum, mas permitido pela estrutura. Por exemplo, billing administrator é um formato de nome de política ou função incomum em aplicativos .NET, mas é um nome de função ou política válido.

Conteúdo exibido durante a autenticação assíncrona

Blazor permite que o estado de autenticação seja determinado de forma assíncrona. O cenário principal para esta abordagem é em aplicações de Blazor do lado do cliente que fazem uma solicitação a um ponto de extremidade externo para autenticação.

Enquanto a autenticação está em andamento, AuthorizeView não exibe conteúdo. Para exibir conteúdo enquanto a autenticação ocorre, atribua o conteúdo ao parâmetro 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>

Essa abordagem normalmente não é aplicável a aplicativos de Blazor do lado do servidor. Os aplicativos Blazor do lado do servidor conhecem o estado de autenticação assim que o estado é estabelecido. O conteúdo Authorizing pode ser fornecido no componente AuthorizeView de um aplicativo, mas nunca é exibido.

[Authorize] atributo

O [Authorize] atributo está disponível em Razor componentes:

@page "/"
@attribute [Authorize]

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

Important

Utilize apenas [Authorize] em componentes @page alcançados através do roteador Blazor. A autorização é executada apenas como um aspeto do roteamento e não para componentes-filho renderizados numa página. Para autorizar a exibição de partes específicas dentro de uma página, use AuthorizeView em vez disso.

O [Authorize] atributo também oferece suporte à autorização baseada em função ou política. Para autorização baseada em função, use o parâmetro Roles:

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

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

Para autorização baseada em política, use o parâmetro Policy:

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

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

Se nem Roles nem Policy for especificado, [Authorize] usará a política padrão:

  • Os usuários autenticados (conectados) são autorizados.
  • Os usuários não autenticados (desconectados) não são autorizados.

Quando o usuário não está autorizado e se o aplicativo não personaliza conteúdo não autorizado com o Router componente, a estrutura exibe automaticamente a seguinte mensagem de fallback:

Not authorized.

Autorização de recursos

Para autorizar usuários para recursos, passe os dados de rota da solicitação para o parâmetro Resource de AuthorizeRouteView.

No conteúdo do Router.Found para uma rota solicitada:

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

Para obter mais informações sobre como os dados de estado de autorização são passados e usados na lógica de procedimento, consulte a seção Expor o estado de autenticação como um parâmetro em cascata.

Quando o AuthorizeRouteView recebe os dados de rota para o recurso, as políticas de autorização têm acesso a RouteData.PageType e RouteData.RouteValues que permitem que a lógica personalizada tome decisões de autorização.

No exemplo a seguir, uma política de EditUser é criada em AuthorizationOptions para a configuração do serviço de autorização do aplicativo (AddAuthorizationCore) com a seguinte lógica:

  • Determine se existe um valor de rota com uma chave de id. Se a chave existir, o valor da rota será armazenado em value.
  • Em uma variável chamada id, armazenevalue como uma cadeia de caracteres ou defina um valor de cadeia de caracteres vazio (string.Empty).
  • Se id não for uma cadeia de caracteres vazia, afirme que a política está satisfeita (retornar true) se o valor da cadeia começar com EMP. Caso contrário, afirme que a política falha (retornar false).

No ficheiro Program:

  • Adicione namespaces para Microsoft.AspNetCore.Components e System.Linq:

    using Microsoft.AspNetCore.Components;
    using System.Linq;
    
  • Adicione a política:

    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;
        })
    );
    

O exemplo anterior é uma política de autorização excessivamente simplificada, usada apenas para demonstrar o conceito com um exemplo de trabalho. Para obter mais informações sobre como criar e configurar políticas de autorização, consulte Autorização baseada em políticas no ASP.NET Core.

No componente EditUser seguinte, o recurso em /users/{id}/edit tem um parâmetro de rota para o identificador do utilizador ({id}). O componente utiliza a anterior política de autorização de EditUser para ver se o valor de rota para id começa com EMP. Se id começar com EMP, a política será bem-sucedida e o acesso ao componente será autorizado. Se id começar com um valor diferente de EMP ou se id for uma cadeia de caracteres vazia, a política falhará e o componente não será carregado.

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; }
}

Personalizar conteúdo não autorizado com o componente Router

O componente Router, em conjunto com o componente AuthorizeRouteView, permite que o aplicativo especifique conteúdo personalizado se:

  • O usuário falha uma condição de [Authorize] aplicada ao componente. A marcação do elemento <NotAuthorized> é exibida. O atributo [Authorize] é abordado na seção atributo [Authorize].
  • A autorização assíncrona está em andamento, o que geralmente significa que o processo de autenticação do usuário está em andamento. A marcação do elemento <Authorizing> é exibida.

Important

Os recursos do roteador Blazor que exibem conteúdo <NotAuthorized> e <NotFound> não estão a funcionar durante a renderização estática do lado do servidor (SSR estático) porque o processamento de solicitações é totalmente gerido pelo pipeline de middleware do ASP.NET Core, e os componentes Razor não são renderizados para solicitações não autorizadas ou incorretas. Use técnicas do lado do servidor para lidar com solicitações não autorizadas e incorretas durante o SSR estático. Para obter mais informações, consulte modos de renderização do ASP.NET Core Blazor.

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

O conteúdo de Authorized e NotAuthorized pode incluir itens arbitrários, como outros componentes interativos.

Note

O anterior requer o registro de serviços de estado de autenticação em cascata no arquivo Program do aplicativo:

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

O conteúdo de NotFound, Authorizede NotAuthorized pode incluir itens arbitrários, como outros componentes interativos.

Se o conteúdo NotAuthorized não for especificado, o AuthorizeRouteView usará a seguinte mensagem de substituição:

Not authorized.

Um aplicativo criado a partir do modelo de projeto Blazor WebAssembly com autenticação habilitada inclui um componente RedirectToLogin, que é posicionado no conteúdo <NotAuthorized> do componente Router. Quando um usuário não é autenticado (context.User.Identity?.IsAuthenticated != true), o componente RedirectToLogin redireciona o navegador para o ponto de extremidade authentication/login para autenticação. O usuário é retornado à URL solicitada após a autenticação com o provedor de identidade.

Lógica processual

Se for necessário que o aplicativo verifique as regras de autorização como parte da lógica processual, use um parâmetro em cascata do tipo Task<AuthenticationState> para obter a ClaimsPrincipaldo usuário. Task< AuthenticationState > pode ser combinado com outros serviços, como IAuthorizationService, para avaliar políticas.

No exemplo a seguir:

  • O user.Identity.IsAuthenticated executa código para usuários autenticados (conectados).
  • O user.IsInRole("admin") executa código para usuários na função 'Admin'.
  • O (await AuthorizationService.AuthorizeAsync(user, "content-editor")).Succeeded executa código para utilizadores que cumpram os requisitos da política 'editor de conteúdo'.

Um aplicativo Blazor do lado do servidor inclui os namespaces apropriados quando criado a partir do modelo de projeto. Em um aplicativo de Blazor do lado do cliente, confirme a presença dos namespaces Microsoft.AspNetCore.Authorization e Microsoft.AspNetCore.Components.Authorization no componente ou no arquivo _Imports.razor do aplicativo:

@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)
                {
                    // ...
                }
            }
        }
    }
}

Solucionar erros

Erros comuns:

  • A autorização requer um parâmetro em cascata do tipo Task<AuthenticationState>. Considere usar CascadingAuthenticationState para fornecer isso.

  • null valor é recebido para authenticationStateTask

É provável que o projeto não tenha sido criado usando um modelo de Blazor do lado do servidor com autenticação habilitada.

No .NET 7 ou anterior, envolva uma <CascadingAuthenticationState> em torno de alguma parte da árvore da interface do usuário, por exemplo, em torno do roteador Blazor:

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

No .NET 8 ou posterior, não use o componente CascadingAuthenticationState:

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

Em vez disso, adicione serviços de estado de autenticação em cascata à coleção de serviços no arquivo Program:

builder.Services.AddCascadingAuthenticationState();

Os serviços fornecidos pelo componente CascadingAuthenticationState (.NET 7 ou anterior) ou pelo AddCascadingAuthenticationState (.NET 8 ou posterior) fornecem o parâmetro em cascata Task<AuthenticationState>, que, por sua vez, recebe do serviço subjacente de injeção de dependência AuthenticationStateProvider.

Informações de identificação pessoal (PII)

A Microsoft usa a definição do GDPR para "dados pessoais" (GDPR 4.1) quando a documentação discute Informações de Identificação Pessoal (PII).

PII refere-se a qualquer informação relativa a uma pessoa singular identificada ou identificável. Uma pessoa singular identificável é aquela que possa ser identificada, direta ou indiretamente, com qualquer um dos seguintes elementos:

  • Name
  • Número de identificação
  • Coordenadas de localização
  • Identificador em linha
  • Outros fatores específicos
    • Physical
    • Physiological
    • Genetic
    • Mental (psicológico)
    • Economic
    • Cultural
    • Identidade social

Recursos adicionais