Autenticação e autorização do Blazor no 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.

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 descreve o suporte do ASP.NET Core para a configuração e o gerenciamento de segurança em aplicativos Blazor.

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.

As convenções de autorização do Razor Pages não se aplicam a componentes Razor roteáveis. Se um componente Razor não roteável for inserido em uma página de um aplicativo do Razor Pages, as convenções de autorização da página afetarão indiretamente o componente Razor junto com o restante do conteúdo da página.

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.

As convenções de autorização do Razor Pages não se aplicam a componentes Razor roteáveis. Se um componente Razor não roteável for inserido em uma página de um aplicativo do Razor Pages, as convenções de autorização da página afetarão indiretamente o componente Razor 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, confira Scaffold ASP.NET CoreIdentity em um aplicativo Blazor do lado do servidor.

Observação

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 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 neste artigo.

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 ASP.NET CoreBlazor Visão geral dos formulários.

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 Chame uma API Web de um Blazoraplicativo ASP.NET Core.

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.

Observação

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

Para saber mais, consulte os recursos a seguir:

Autenticação

O Blazor usa os mecanismos de autenticação do ASP.NET Core existentes 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.

Autenticação de Blazor do lado do servidor

O lado do servidor renderizado interativamente Blazor opera em uma conexão SignalR com o cliente. A autenticação em aplicativos baseados em SignalR é realizada quando a conexão é estabelecida. 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 serviço AuthenticationStateProvider interno obtém dados de estado de autenticação de 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.

IHttpContextAccessor/HttpContext em componentes Razor

IHttpContextAccessor deve ser evitado com a renderização interativa porque não há um HttpContext disponível válido.

IHttpContextAccessor pode ser usado para componentes que são renderizados estaticamente no servidor. No entanto, recomendamos evitá-lo, se possível.

HttpContext pode ser usado como um parâmetro em cascata apenas em componentes raiz renderizados estaticamente para tarefas gerais, como inspecionar e modificar cabeçalhos ou outras propriedades no componente App (Components/App.razor). O valor é sempre null para renderização interativa.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

Para cenários em que o componente HttpContext é necessário em componentes interativos, recomendamos fluir os dados por meio do estado de componente persistente do servidor. Para obter mais informações, confira Cenários de segurança adicionais Blazor do ASP.NET Core do lado do servidor.

Não use IHttpContextAccessor/HttpContext direta ou indiretamente nos componentes Razor dos aplicativos Blazor do lado do servidor. Os aplicativos Blazor são executados fora do contexto do pipeline ASP.NET Core. Não há garantia de que o HttpContext esteja disponível no IHttpContextAccessor e não há garantia de que o HttpContext mantenha o contexto que iniciou o aplicativo Blazor.

A abordagem recomendada para passar o estado da solicitação para o aplicativo Blazor é por meio de parâmetros de componente raiz durante a renderização inicial do aplicativo. Como alternativa, o aplicativo pode copiar os dados para um serviço com escopo no evento de ciclo de vida de inicialização do componente raiz para uso em todo o aplicativo. Para obter mais informações, confira Cenários de segurança adicionais Blazor do ASP.NET Core do lado do servidor.

Um aspecto crítico da segurança de Blazor do lado do servidor é que o usuário anexado a determinado circuito pode ser atualizado em algum momento após o circuito Blazor ser estabelecido, mas o IHttpContextAccessornão ser atualizado. Para obter mais informações sobre como lidar com essa situação usando serviços personalizados, confira Outros cenários de segurança do ASP.NET Core Blazor do lado do servidor.

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.

Aviso

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 diretrizes gerais sobre o gerenciamento de estado, confira Gerenciamento de estado Blazor do ASP.NET Core.

Autenticação de Blazor do lado do cliente

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, o uso do serviço AuthenticationStateProvider interno ou personalizado é abordado nas seções a seguir.

Para obter mais informações, confira Proteger o ASP.NET Core Blazor WebAssembly.

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.

Observação

Para implementar um AuthenticationStateProvider personalizado, confira Aplicativos Blazor seguros do lado do servidor do ASP.NET Core.

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

ClaimsPrincipalData.razor:

@page "/claims-principle-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

@if (claims.Count() > 0)
{
    <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-principle-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

@if (claims.Count() > 0)
{
    <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 DI (injeção de dependência) e serviços, consulte Injeção de dependência de Blazor do ASP.NET Core e Injeção de dependência no ASP.NET Core. Para obter informações sobre como implementar um AuthenticationStateProvider personalizado em aplicativos Blazor do lado do servidor, confira Aplicativos Blazor seguros do lado do servidor do ASP.NET Core.

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 do procedimento, como ao realizar 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>, conforme demonstrado no 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 componentes AuthorizeRouteView e CascadingAuthenticationState.

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>

Observação

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

Em um aplicativo Blazor do lado do cliente, adicione serviços para opções e 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.

Autorização

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

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

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

Todos esses conceitos são iguais no MVC do ASP.NET Core ou em aplicativos Razor Pages. Para obter mais informações sobre a segurança do ASP.NET Core, confira os artigos em Segurança e Identity do ASP.NET Core.

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="SecureMethod">Authorized Only Button</button></p>
    </Authorized>
    <NotAuthorized>
        <p>You're not authorized.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    private void SecureMethod() { ... }
}

Um manipulador de eventos padrão para um elemento autorizado, como o método SecureMethod para o elemento <button> no exemplo anterior, só pode ser invocado por um usuário autorizado.

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

Aviso

A marcação do lado do cliente e os métodos associados a um AuthorizeView são protegidos apenas contra exibição e execução na interface do usuário renderizada em aplicativos Blazor do lado do cliente. 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 de segurança adicionais 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 o acesso ou as opções da interface do usuário, 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 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 em políticas

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

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 com a abordagem padrão para acessar o 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 parâmetro Policy com uma única 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.

Caso o usuário precise atender a 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 Autorização baseada em política no ASP.NET Core.

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 por padrão, 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

O Blazor permite que o estado de autenticação seja determinado de modo assíncrono. 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 por padrão. 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 atributo [Authorize] está disponível em componentes Razor:

@page "/"
@attribute [Authorize]

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

Importante

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 atributo [Authorize] também dá suporte à autorização baseada em funções ou em políticas. 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 componente Router, 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 de 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 permite 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 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:

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

Importante

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 ASP.NET Core Blazor modos de renderização.

<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.

Observação

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 por padrão 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 problemas de erros

Erros comuns:

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

  • O valor null é 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 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 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:

  • Nome
  • Número de identificação
  • Coordenadas de localização
  • Identificador online
  • Outros fatores específicos
    • Físico
    • Fisiológicos
    • Genéticos
    • Mentais (psicológicos)
    • Económicos
    • Cultural
    • Identidade social

Recursos adicionais