Compartilhar via


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

Note

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

Warning

Esta versão do ASP.NET Core não tem mais suporte. 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 do .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 existentes do ASP.NET Core para estabelecer a identidade do usuário. O mecanismo exato depende de como o aplicativo Blazor está hospedado, no 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 são capazes de impor regras de acesso para áreas do aplicativo e componentes. Como a execução do código do lado do cliente pode ser adulterada, não se pode confiar no código de autorização em execução no cliente para impor regras de acesso ou controlar a exibição do conteúdo do lado do cliente.

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

Se a aplicação das regras 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 de páginas não se aplicam a componentes roteáveis Razor . Se um componente não roteável Razor estiver embutido em uma página de um aplicativo Pages Razor, as convenções de autorização da página têm um impacto indireto sobre o Razor componente, junto com o restante do conteúdo da página.

O 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. Os aplicativos ASP.NET Core que usam o ASP.NET Core Identity para gerenciamento de usuários devem usar Razor Pages em vez de componentes Razor para interface do usuário relacionada a Identity, como registro de usuário, logon, logoff e outras tarefas de gerenciamento de usuários. A criação de componentes Razor que lidam diretamente com tarefas Identity é possível para vários cenários, mas não é recomendada ou compatível com a Microsoft.

Abstrações do ASP.NET Core, como SignInManager<TUser> eUserManager<TUser>, não têm suporte em componentes Razor. Para obter mais informações sobre como usar o ASP.NET Core Identity com Blazor, veja Scaffold ASP.NET Core Identity em um aplicativo Blazor do lado do servidor.

Note

Os exemplos de código neste artigo adotam NRTs (tipos de referência anuláveis) e análise estática de estado nulo do compilador .NET, que têm suporte 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 do aplicativo, cadeias de conexão, credenciais, senhas, PINs (números de identificação pessoal), código .NET/C# privado ou chaves/tokens privados no código do lado do cliente, que é sempre inseguro. O código do lado Blazor do cliente deve acessar serviços e bancos de dados seguros por meio de uma API Web segura que você controla.

Em ambientes de teste/preparo e produção, o código do lado do Blazor servidor e as APIs Web devem usar fluxos de autenticação seguros que evitam 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 Gerenciador de Segredos é recomendada para proteger dados confidenciais. Para saber mais, consulte os recursos a seguir:

Para desenvolvimento e teste locais do lado do cliente e do servidor, use a ferramenta Gerenciador de Segredos para proteger credenciais confidenciais.

Identidades gerenciadas para serviços do Microsoft Azure

Para os serviços do Microsoft Azure, recomendamos o uso de identidades gerenciadas. As identidades gerenciadas autenticam de maneira segura para serviços do Azure sem armazenar credenciais no código do aplicativo. Para saber mais, consulte os recursos a seguir:

Suporte à anti-falsificação

O modelo Blazor:

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

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

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

Note

A mitigação de antiforgeria só é necessária ao enviar dados de formulário para o servidor codificado como application/x-www-form-urlencoded, multipart/form-dataou text/plain como esses são os únicos tipos de formulário válidos.

Para saber mais, consulte os recursos a seguir:

Autenticação de Blazor do lado do servidor

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

O contexto de autenticação só é estabelecido quando o aplicativo é iniciado, que é quando o aplicativo se conecta pela primeira vez ao WebSocket em uma SignalR conexão com o cliente. A autenticação pode ser baseada em um cookie ou em outro token de portador, mas a autenticação é gerenciada por meio do hub SignalR e totalmente 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 o aplicativo 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 cenários de segurança adicionais.

Blazor difere dos aplicativos Web renderizados pelo 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, cookies não estão envolvidos. Cookies são enviados somente ao fazer uma solicitação HTTP a um servidor, o que não ocorre quando o usuário navega em um aplicativo do Blazor. Durante a navegação, o estado de autenticação do usuário é verificado dentro do Blazor circuito, que você pode atualizar a qualquer momento no servidor usando a RevalidatingAuthenticationStateProvider abstração.

Important

Não é recomendável implementar um NavigationManager personalizado para obter validação de autenticação durante a navegação. Se o aplicativo precisar executar a lógica de estado de autenticação personalizada durante a navegação, use um personalizado AuthenticationStateProvider.

Note

Os exemplos de código neste artigo adotam NRTs (tipos de referência anuláveis) e análise estática de estado nulo do compilador .NET, que têm suporte 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.

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

Estado compartilhado

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

Warning

Não recomendamos que os aplicativos no mesmo estado de compartilhamento de servidor usem serviços singleton, a menos que sejam tomados cuidados extremos, pois isso pode introduzir vulnerabilidades de segurança, como o vazamento do estado do usuário entre circuitos.

Você pode usar serviços singleton com estado em aplicativos Blazor, se forem criados 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 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 vazará entre circuitos.

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

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

Em ambientes de teste/preparo e produção, o código do lado do Blazor servidor e as APIs Web devem usar fluxos de autenticação seguros que evitam 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 Gerenciador de Segredos é recomendada para proteger dados confidenciais. Para saber mais, consulte os recursos a seguir:

Para desenvolvimento e teste locais do lado do cliente e do servidor, use a ferramenta Gerenciador de Segredos para proteger credenciais confidenciais.

Modelo de projeto

Crie um novo aplicativo do lado Blazor do servidor seguindo as diretrizes 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): nenhuma autenticação.
  • Contas individuais: as contas de usuário são armazenadas no aplicativo usando ASP.NET Core Identity.
  • Nenhum (padrão): nenhuma 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: Usar a Autenticação do Windows.

Interface do usuário BlazorIdentity (contas individuais)

O Blazor dá suporte à geração de uma interface do usuário Blazor completa baseada no Identity quando você escolhe a opção de autenticação para Contas Individuais.

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

O modelo :

  • é compatível com cenários de SSR interativa (renderização do lado do servidor interativa) 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 dos usuários. Os Identity componentes também dão suporte a recursos avançados Identity , como confirmação de conta e recuperação de senha e autenticação multifator usando um aplicativo de terceiros. Os componentes Identity em si não suportam interatividade.
  • Adiciona os pacotes e dependências relacionados a 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 os pontos de extremidade Identity internos.
  • Inclui validação de Identity e lógica de negócios.

Para inspecionar os componentes do framework, acesse-os nas pastas Blazor e Identity da pasta Pages no projeto do servidor do modelo de projeto Shared (Components/Account repositório GitHub).

Quando você escolhe os modos de renderização Interativa WebAssembly ou Interativa Auto, o servidor lida com todas as solicitações de autenticação e autorização, e os componentes Identity são renderizados de forma estática no servidor no projeto principal do Blazor Web App.

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

Somente para soluções do Interactive Server, 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 em que um circuito interativo está ativo.

Quando você escolhe os modos de renderização Interativa WebAssembly ou Interativa Auto, o servidor lida com todas as solicitações de autenticação e autorização, e os componentes Identity são renderizados de forma estática no servidor no projeto principal do Blazor Web App. O modelo de projeto inclui uma PersistentAuthenticationStateProvider classe (origem de referência) no .Client projeto para sincronizar o estado de autenticação do usuário entre o servidor e o navegador. A classe é uma implementação personalizada de AuthenticationStateProvider. O provedor usa o serviço de Estado de Componente Persistente (PersistentComponentState) para pré-gerar o estado de autenticação e persistê-lo na página.

No projeto principal de um , o provedor de estado de autenticação é denominado na pasta do projeto servidor no modelo de projeto ( no repositório GitHub) (somente para soluções de interatividade do servidor) ou denominado (para soluções de interatividade WebAssembly ou Auto) na mesma pasta.

Blazor Identity depende DbContext de instâncias não criadas por uma fábrica, o que é intencional porque DbContext é suficiente para que os componentes do modelo de Identity projeto sejam renderizados estaticamente sem dar 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 ASP.NET Core Blazor Modos de renderização.

Para obter mais informações sobre a persistência do estado pré-gerado, consulte ASP.NET Persistência de estado prerendered coreBlazor.

Note

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. Para obter mais informações, consulte Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

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

Esta seção se aplica a Blazor Web Apps que adotam:

  • Contas Individuais
  • Renderização no lado do cliente (CSR, interatividade baseada em WebAssembly).

Um provedor de estado de autenticação do lado do cliente é usado somente em Blazor e não está integrado ao sistema de autenticação do 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, é usado um provedor de autenticação no lado do cliente. Quando o usuário atualiza a página (recarrega a 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 é mantido pelo servidor, qualquer estado de autenticação mantido no lado do cliente é perdido.

Para resolver isso, a melhor abordagem é realizar a autenticação no sistema de autenticação do ASP.NET Core. O provedor de estado de autenticação no lado do cliente só se encarrega 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 do Blazor Web App e descritos abaixo.

No arquivo Program do projeto do servidor, chame AddAuthenticationStateSerialization, que, usando o serviço AuthenticationState (AuthenticationStateProvider), serializa o retornado pelo PersistentComponentState do lado do servidor:

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

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

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

No arquivo .Client do projeto do cliente (Program), chame AddAuthenticationStateDeserialization, que adiciona um AuthenticationStateProvider em que o AuthenticationState é desserializado do servidor usando AuthenticationStateData e o serviço Estado Persistente do Componente (PersistentComponentState). Deve haver uma chamada correspondente para AddAuthenticationStateSerialization no projeto do 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 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. Para obter mais informações, consulte Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Andaime Identity

Para obter mais informações sobre a estruturação Identity em um aplicativo servidor Blazor, consulte Estruturação Identity em projetos do ASP.NET Core.

Faça scaffold Identity em um aplicativo Blazor do lado do servidor:

Declarações e tokens adicionais de provedores externos

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

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

Especifique o emissor explicitamente ao implantar no Serviço de Aplicativo do Azure no Linux com o Identity Server. Para obter mais informações, confira Usar o Identity para proteger um back-end da API Web para SPAs.

Injetar AuthenticationStateProvider para serviços com escopo para 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 está inicializada corretamente.

Para acessar o AuthenticationStateProvider dentro de um serviço com escopo especificamente para um componente, injetar o AuthenticationStateProvider no componente e transmiti-lo para o serviço como um parâmetro. Essa abordagem garante que a instância correta inicializada do AuthenticationStateProvider seja usada para cada instância de aplicativo de 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.";
        }
    }
}

Registre o serviço como com escopo. Em um aplicativo 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 arquivo Program:

builder.Services.AddScoped<ExampleService>();

No Startup.ConfigureServices do 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 diretrizes de OwningComponentBase em Injeção de dependência Blazor no ASP.NET Core.

Conteúdo não autorizado exibido durante a pré-renderização com um AuthenticationStateProvider personalizado

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

  • Desabilitar a 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 com base no modelo de projeto do 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, desabilite a pré-geração para o componente HeadOutlet:

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

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

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

    <component type="typeof(App)" render-mode="Server" />
    
  • Autenticar o usuário no servidor antes de iniciar o aplicativo: Para adotar essa abordagem, o aplicativo deve responder à solicitação inicial de um usuário com a página ou exibição de login baseada em Identity e impedir qualquer solicitação a endpoints Blazor até que haja a autenticação. 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 realmente não está autorizado a exibir 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 como ele está conectado.

A autenticação usa a mesma autenticação Identity do ASP.NET Core 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 diretrizes nos artigos e tutoriais Identity do ASP.NET Core para que os recursos Identity entrem em vigor nas partes Blazor do aplicativo.

Para obter diretrizes sobre o gerenciamento geral de estado fora do ASP.NET CoreIdentity, consulte ASP.NET Visão geral do gerenciamento de estado do CoreBlazor.

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 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. Para obter mais informações, consulte Como selecionar uma marca de versão do código-fonte do 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);

Gerenciamento de estado de autenticação na saída

O Blazor no lado do servidor mantém o estado de autenticação do usuário durante toda a duração do circuito, inclusive entre guias do navegador. Para encerrar proativamente a sessão de um usuário em todas as guias do navegador quando ele sai de uma delas, é necessário implementar um RevalidatingServerAuthenticationStateProvider (fonte de referência) com um breve RevalidationInterval.

Note

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. Para obter mais informações, consulte Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

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

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

Use a opção RazorComponentsServiceOptions.TemporaryRedirectionUrlValidityDuration para obter ou definir o período de validade da proteção de dados do ASP.NET Core para URLs de redirecionamento temporário emitidas pela renderização do lado do servidor Blazor. Eles são usados apenas transitoriamente, portanto, o tempo de vida só precisa ser longo o suficiente para que um cliente receba a URL e inicie a navegação nela. No entanto, também deve ser longo o suficiente para permitir a distorção do relógio entre os 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 no lado do cliente Blazor

Em aplicativos do lado do cliente Blazor, as verificações de autenticação do lado do cliente podem ser ignoradas porque todo o código do lado do cliente pode ser modificado pelos usuários. Isso também ocorre com todas as tecnologias de aplicativo do lado do cliente, incluindo estruturas de SPA do JavaScript e aplicativos nativos em qualquer sistema operacional.

Adicione o seguinte:

Para lidar com a autenticação, use um serviço 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 dados em Blazor Web Apps com renderização automática interativa

Quando um adota renderização do lado do servidor (SSR) e 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 todos os dados obtidos) quando renderizado 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 por meio dos endpoints da API web do servidor chamados pelo cliente. É necessário ter cuidado ao proteger o acesso a dados em ambos os locais para impedir o acesso inadequado a dados.

Considere o cenário a seguir em que os dados meteorológicos seguros são exibidos por um componente. Demonstrações de algumas das abordagens a seguir podem ser avaliadas e testadas usando os BlazorWebAppEntra/BlazorWebAppEntraBffexemplos (.NET 9 ou posterior) ou os BlazorWebAppOidc/BlazorWebAppOidcBff exemplos (.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 de 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 do cliente implementa IWeatherForecaster. O método GetWeatherForecastAsync chama uma API da Web do projeto de 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 do servidor implementa IWeatherForecaster como ServerWeatherForecaster, o que gera e retorna dados meteorológicos por meio de seu GetWeatherForecastAsync método:

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 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, você pode injetar uma fábrica de clientes HTTP (IHttpClientFactory) no ServerWeatherForecaster e chamar uma API Web externa usando um cliente HTTP nomeado com um manipulador de token. Para obter mais informações, consulte Chamar uma API Web de um aplicativo ASP.NET CoreBlazor.

Se o aplicativo usar a plataforma de identidade Microsoft com os pacotes Microsoft Identity Web para o Microsoft Entra ID (consulte Chamar uma API da Web de um aplicativo ASP.NET Core Blazor), o ServerWeatherForecaster a seguir demonstra como fazer uma chamada para uma API da Web externa. O token de acesso é anexado automaticamente à 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 do servidor mantém um ponto de extremidade seguro de API da Web para as chamadas de dados meteorológicos feitas pelos clientes. Esse endereço resulta em uma chamada ServerWeatherForecaster.GetWeatherForecastAsync no servidor:

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

Usando a abordagem anterior, há dois sistemas em vigor 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 é imposta pelo atributo do [Authorize]componente. Em resumo, a segurança dos dados meteorológicos é imposta pelo componente.
  • Quando o componente Weather é renderizado no cliente, o serviço ClientWeatherForecaster é usado para fazer uma chamada de API web ao ponto de extremidade seguro /weather-forecast que aplica o método de extensão RequireAuthorization. Se o usuário tiver autoridade para acessar dados meteorológicos, o endpoint usará o serviço ServerWeatherForecaster para chamar GetWeatherForecastAsync. Os dados são retornados ao cliente. Em resumo, a segurança dos dados meteorológicos é garantida pelo endpoint da API web do aplicativo de servidor.

A abordagem anterior funciona bem quando os requisitos de segurança da API 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 Web e ao componente.

Cenários complexos exigem planejamento e implementação adicionais. Por exemplo, uma API Web do servidor que tem 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.

À medida que você cria segurança em aplicativos que adotam a 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 de serviço do servidor que é usada quando um componente é renderizado no servidor e acessa dados por meio do serviço. Avalie cuidadosamente a diferença entre acessar dados no servidor durante o SSR em vez de acessar os dados em uma solicitação de API Web do cliente durante a CSR. Aplique estrategicamente a segurança para evitar o acesso inadequado aos dados.

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

  • BlazorWebAppOidc
  • BlazorWebAppOidcBff
  • BlazorWebAppEntra
  • BlazorWebAppEntraBff

Serviço AuthenticationStateProvider

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

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

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

Para implementar um estado personalizadoAuthenticationStateProvider, consulte ASP.NET estado de autenticação principalBlazor, que inclui diretrizes sobre como implementar notificações de alteração de estado de autenticação do usuário.

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 como o usuário é um ClaimsPrincipal, será possível enumerar as declarações e avaliar a associação nas funções.

Para obter mais informações sobre Injeção de Dependência (DI) e serviços, consulte Injeção de Dependência no 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 ASP.NET Core estado de autenticaçãoBlazor.

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

Se os dados de estado de autenticação forem necessários para a lógica de procedimento, como ao executar uma ação disparada pelo usuário, obtenha os dados de 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, será possível enumerar as declarações e avaliar a associação nas funções.

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

Ao criar 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. Um aplicativo Blazor do lado do cliente também inclui os registros de serviço necessários. Informações adicionais são apresentadas na seção Personalizar 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 Task<AuthenticationState>parâmetro em cascata usando os AuthorizeRouteView e CascadingAuthenticationState componentes.

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

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

Note

Com a versão do .NET 5.0.1 e para quaisquer versões adicionais de 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.

Em um aplicativo Blazor do cliente, adicione serviços de autorização ao arquivo Program:

builder.Services.AddAuthorizationCore();

Em um aplicativo Blazor do cliente, adicione opções e serviços de autorização ao arquivo Program:

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

Em um aplicativo 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.

O acesso geralmente é concedido ou negado com base nos seguintes casos:

  • O usuário está autenticado (conectado).
  • Se o usuário está em uma função.
  • Um usuário tem uma declaração.
  • Se uma política é atendida.

Todos esses conceitos são os mesmos em um aplicativo MVC do ASP.NET Core ou Razor Pages. Para obter mais informações sobre a segurança do ASP.NET Core, consulte os artigos em ASP.NET Core Security e Identity.

Componente AuthorizeView

O componente AuthorizeView exibe de modo seletivo o conteúdo da interface do usuário, caso o usuário esteja autorizado. Essa abordagem é útil quando você precisa apenas exibir dados para o usuário e não precisa usar a identidade dele na lógica de procedimento.

O componente expõe uma variável context do tipo AuthenticationState (@context na sintaxe Razor), que pode ser usada 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 AuthorizeView componente 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 HandleClick método é associado apenas a um botão visível para usuários autorizados, mas nada impede a invocação desse método de outros lugares. Para garantir a segurança no nível do método, implemente a lógica de autorização adicional no próprio manipulador ou na API relevante.

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

Warning

A marcação do lado do cliente e os métodos 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 os métodos seguros no Blazor do lado do cliente, o conteúdo geralmente é fornecido por uma chamada segura e autorizada da API Web para uma API do lado do servidor e nunca é armazenado no aplicativo. Para obter mais informações, consulte Chamar uma API Web de um aplicativo ASP.NET Core Blazor e Cenários adicionais de segurança do ASP.NET Core Blazor 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 opções de interface do usuário ou acesso, são abordadas na seção Autorização .

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

  • Usuários autenticados (conectados) estão autorizados.
  • Usuários não autenticados (não conectados) não estão autorizados.

O componente AuthorizeView pode ser usado no componente NavMenu (Shared/NavMenu.razor) para exibir um componente NavLink (NavLink), mas observe que essa abordagem remove apenas o item da 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 em políticas

O AuthorizeView componente dá suporte à autorização baseada em função ou baseada em política .

Para a autorização baseada em funções, 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 usuário 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 estabelece um Context para o componente interno AuthorizeView para evitar uma colisão de contexto AuthenticationState. O contexto AuthenticationState é acessado no AuthorizeView externo utilizando a abordagem padrão para acesso ao contexto (@context.User). O contexto é acessado no AuthorizeView internos 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 Policy parâmetro com um único nome de política:

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

Caso o usuário precise cumprir uma das várias políticas, crie uma política que confirme que o usuário atende a outras políticas.

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

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

  • Aninhar 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 exige que os usuários tenham determinada declaração. Para obter mais informações, consulte a autorização baseada em política no ASP.NET Core.

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

Se Roles e Policy não forem especificados, o AuthorizeView usará a política padrão:

  • Usuários autenticados (conectados) estão autorizados.
  • Usuários não autenticados (não conectados) não estão autorizados.

Como as comparações de cadeia de caracteres do .NET diferenciam maiúsculas de minúsculas, a correspondência de nomes de função e política também diferencia maiúsculas de minúsculas. Por exemplo, Admin (A em maiúsculas) não é tratado como a mesma função que admin (a em minúsculas).

O caso Pascal normalmente é usado para nomes de função e política (por exemplo, BillingAdministrator), mas o uso do caso Pascal não é um requisito estrito. Diferentes esquemas de uso de maiúsculas e minúsculas, como maiúsculas e minúsculas concatenadas, kebab e snake são permitidos. O uso de espaços em nomes de função e política é incomum, mas permitido pela estrutura. Por exemplo, billing administrator é um formato incomum de função ou nome de política em aplicativos .NET, mas é uma função ou nome de 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 dessa abordagem ocorre em aplicativos Blazor do lado do cliente que fazem uma solicitação a um ponto de extremidade externo para autenticação.

Enquanto a autenticação estiver em andamento, AuthorizeView não exibirá nenhum conteúdo. Para exibir o conteúdo durante a autenticação, atribua 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>

Normalmente, essa abordagem não é aplicável a aplicativos Blazor do lado do servidor. Os aplicativos Blazor do lado do servidor ficam conhecendo o estado de autenticação assim que ele é estabelecido. O conteúdo Authorizing pode ser fornecido em um componente AuthorizeView do aplicativo, mas o conteúdo nunca é exibido.

Atributo [Authorize]

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

@page "/"
@attribute [Authorize]

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

Important

Use [Authorize] somente em componentes @page acessados por meio do roteador Blazor. A autorização é realizada apenas como um aspecto do roteamento e não para componentes filho renderizados dentro de uma página. Para autorizar a exibição de partes específicas dentro de uma página, use AuthorizeView.

O [Authorize] atributo também dá suporte à autorização baseada em função ou baseada em política. Para a autorização baseada em funções, 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 a autorização baseada em políticas, use o parâmetro Policy:

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

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

Se Roles e Policy não forem especificados, o [Authorize] usará a política padrão:

  • Usuários autenticados (conectados) estão autorizados.
  • Usuários não autenticados (não conectados) não estão autorizados.

Quando o usuário não está autorizado e se o aplicativo não personalizar conteúdo não autorizado com o Router componente, a estrutura exibirá 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 Router.Found referente a 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 uma seção de 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 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, armazene value 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 será atendida (retornar true) se o valor da cadeia de caracteres começar com EMP. Caso contrário, declare que a política falhará (retornar false).

No arquivo 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 simplificada, usada apenas para demonstrar o conceito com um exemplo em funcionamento. Para obter mais informações sobre como criar e configurar políticas de autorização, consulte autorização baseada em política no ASP.NET Core.

No componente EditUser a seguir, o recurso em /users/{id}/edit tem um parâmetro de rota para o identificador do usuário ({id}). O componente usa a política de autorização EditUser anterior para determinar se o valor da rota para id começa com EMP. Se id começar com EMP, a política terá êxito e o acesso ao componente será autorizado. Se id começar com um valor diferente 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 o conteúdo não autorizado com o componente Router

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

Important

Os recursos do roteador Blazor que exibem o conteúdo <NotAuthorized> e <NotFound> não estão operacionais durante a renderização estática do lado do servidor (SSR estática) porque o processamento de solicitações é totalmente tratado pelo processamento de solicitações do 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 ruins durante a SSR estática. Para obter mais informações, consulte os modos de renderização do ASP.NET CoreBlazor.

<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 mencionado anteriormente requer o registro dos 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, Authorized e NotAuthorized pode incluir itens arbitrários, como outros componentes interativos.

Se o conteúdo NotAuthorized não for especificado, o AuthorizeRouteView usará a mensagem de fallback a seguir:

Not authorized.

Um aplicativo criado a partir do modelo de projeto Blazor WebAssembly com a 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 de procedimento

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

No exemplo a seguir:

  • O user.Identity.IsAuthenticated executa o código para usuários autenticados (conectados).
  • O user.IsInRole("admin") executa o código para usuários na função de "Administrador".
  • O (await AuthorizationService.AuthorizeAsync(user, "content-editor")).Succeeded executa o código para usuários que satisfazem a política de "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 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 o valor é recebido para authenticationStateTask

Provavelmente, o projeto não foi criado usando um modelo Blazor do lado do servidor com a autenticação habilitada.

No .NET 7 ou versão anterior, encapsule um <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 versão 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();

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

PII (Informações de Identificação Pessoal)

A Microsoft usa a definição de RGPD para 'dados pessoais' (RGPD 4.1) quando a documentação discute informações de identificação pessoal (PII).

PII refere-se a qualquer informação relacionada a uma pessoa natural identificada ou identificável. Uma pessoa natural identificável é aquela que pode ser identificada, direta ou indiretamente, com qualquer uma das seguintes opções:

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

Recursos adicionais