Proteger aplicativos Blazor do lado do servidor do ASP.NET Core

Observação

Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Aviso

Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, confira .NET e a Política de Suporte do .NET Core. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Importante

Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Este artigo explica como proteger aplicativos Blazor do lado do servidor como aplicativos ASP.NET Core.

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 Tópicos de segurança do ASP.NET Core.

O contexto de autenticação só é estabelecido quando o aplicativo é iniciado, ou seja, quando o aplicativo se conecta pela primeira vez ao WebSocket. 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 para o usuário, confira Cenários de segurança adicionais do Blazor do ASP.NET Core do lado do servidor.

Blazor difere de aplicativos Web tradicionais renderizados pelo servidor 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 circuito Blazor, que você pode atualizar a qualquer momento no servidor usando a abstração RevalidatingAuthenticationStateProvider.

Importante

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.

Observação

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 do .NET, que têm suporte no ASP.NET Core no .NET 6 ou posterior. Ao usar o ASP.NET Core 5.0 ou anterior, remova a designação de tipo nulo (?) dos exemplos deste artigo.

Modelo de projeto

Crie um novo aplicativo Blazor do lado do servidor seguindo as diretrizes em Ferramentas para Blazor do ASP.NET Core.

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 identity da Microsoft: para mais informações, consulte Autenticação e autorização do ASP.NET Core Blazor.
  • Windows: use a Autenticação do Windows.

Interface do usuário BlazorIdentity (contas individuais)

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

O modelo do Blazor Web App faz o scaffold de código do Identity em 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 componentes IdentityRazor e lógica relacionada para tarefas de autenticação de rotina, como conectar e desconectar usuários. Os componentes Identity também são compatíveis com recursos avançados de 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 Identity da estrutura Blazor, acesse-os nas pastas Pages e Shared da pasta da Account no modelo de projeto do Blazor Web App (fonte de referência).

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

A estrutura fornece um AuthenticationStateProvider personalizado nos projetos do servidor e do cliente (.Client) para o fluxo do 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 mais informações, consulte a seção Gerenciar o estado da autenticação em Blazor Web Apps.

Somente para soluções de Servidor Interativo, IdentityRevalidatingAuthenticationStateProvider (fonte de referência) é um AuthenticationStateProvider lado do servidor que revalida o carimbo de segurança do usuário conectado a cada 30 minutos em que um circuito interativo está conectado.

Quando você escolhe os modos de renderização interativa WebAssembly ou renderização automática, o servidor lida com todas as solicitações de autenticação e autorização, e os componentes Identity são renderizados estaticamente no servidor no projeto principal do Blazor Web App. O modelo de projeto inclui uma classe PersistentAuthenticationStateProvider (fonte de referência) no projeto .Client 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 Estado Persistente do Componente (PersistentComponentState) para pré-renderizar o estado de autenticação e mantê-lo na página.

No projeto principal de um Blazor Web App, o provedor de estado de autenticação se chama IdentityRevalidatingAuthenticationStateProvider (fonte de referência) (somente as soluções de interatividade do servidor) ou PersistingRevalidatingAuthenticationStateProvider (fonte de referência) (soluções de interatividade WebAssembly ou Automática).

BlazorIdentity depende de instâncias DbContext não criadas por uma fábrica, o que é intencional porque DbContext é suficiente para que os componentes Identity do modelo de 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 como persistir o estado pré-renderizado, confira Pré-renderizar componentes do ASP.NET Core Razor .

Para mais informações sobre a interface do usuário do BlazorIdentity, bem como diretrizes de como integrar logons externos por meio de redes sociais, consulte Novidades de identity no .NET 8.

Observação

Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira 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 serializa o AuthenticationState retornado pelo AuthenticationStateProvider do lado do servidor usando o serviço Estado Persistente do Componente (PersistentComponentState):

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 Program do projeto do cliente (.Client), 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();

Observação

Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Scaffold Identity

Para obter mais informações sobre scaffolding Identity em um aplicativo Blazor do lado do servidor, confira Scaffolding Identity em projetos 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 Aplicativo do Azure no Linux com o 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 para um componente, injete o AuthenticationStateProvider com a diretiva @inject ou o atributo [Inject] e passe-o 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.

Exibição de conteúdo não autorizado 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.

    Observação

    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, confira Modos de renderização do ASP.NET Core Blazor.

  • 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 logon baseada em Identity e impedir qualquer solicitação a pontos de extremidade Blazor até que haja a autenticação. Para obter mais informações, confira Criar um aplicativo ASP.NET Core com dados de 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 sem Blazor adicionar código 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 de estado geral fora do ASP.NET Core Identity, consulte Gerenciamento de estado Blazor do ASP.NET Core.

Abstrações de segurança adicionais

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

Observação

Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

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

O lado do servidor Blazor persiste o estado de autenticação do usuário durante o tempo de vida do circuito, inclusive nas guias do navegador. Para desconectar proativamente um usuário nas guias do navegador quando o usuário sair de uma guia, você deve implementar um RevalidatingServerAuthenticationStateProvider (fonte de referência) com um RevalidationInterval curto.

Observação

Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira 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 aplica a Blazor Web Apps.

Use a opção RazorComponentsServiceOptions.TemporaryRedirectionUrlValidityDuration para obter ou definir o tempo de vida da validade da Proteção de dados do ASP.NET Core para URLs de redirecionamento temporário emitidas pela renderização do lado do servidor do 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));

Recursos adicionais