Autenticación y autorización de ASP.NET Core Blazor

Nota

Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión .NET 8 de este artículo.

Importante

Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

Para la versión actual, consulte la versión .NET 8 de este artículo.

En este artículo se describe la compatibilidad de ASP.NET Core con la configuración y administración de la seguridad en aplicaciones Blazor.

Los escenarios de seguridad difieren entre el código de autorización que se ejecuta en el lado servidor y el lado cliente en aplicaciones Blazor. Para el código de autorización que se ejecuta en el servidor, las comprobaciones de autorización pueden aplicar reglas de acceso para las áreas de la aplicación y los componentes. Como la ejecución de código del lado cliente se puede alterar, el código de autorización que se ejecuta en el cliente no puede ser de confianza para aplicar absolutamente reglas de acceso ni controlar la visualización del contenido del lado cliente.

Si se debe garantizar la aplicación de reglas de autorización, no implemente comprobaciones de autorización en el código del lado cliente. Compile una aplicación web de Blazor que solo se base en la representación del lado servidor (SSR) para las comprobaciones de autorización y la aplicación de reglas.

Las convenciones de autorización de Razor Pages no se aplican a los componentes de Razor enrutables. Si se inserta un componente de Razor no enrutable de una aplicación de páginas de Razor, las convenciones de autorización de la página afectan indirectamente al componente de Razor y al resto del contenido de la página.

Si se debe garantizar la aplicación de reglas de autorización y la seguridad de los datos y el código, no desarrolle una aplicación del lado cliente. Compile una aplicación de Blazor Server.

Las convenciones de autorización de Razor Pages no se aplican a los componentes de Razor enrutables. Si se inserta un componente de Razor no enrutable de una aplicación de páginas de Razor, las convenciones de autorización de la página afectan indirectamente al componente de Razor y al resto del contenido de la página.

ASP.NET Core Identity está diseñado para funcionar en el contexto de la comunicación de solicitud y respuesta HTTP, que por lo general no es el modelo de comunicación de cliente-servidor de Blazor aplicación. ASP.NET Aplicaciones principales que usan ASP.NET Core Identity para la administración de usuarios deben usar Razor Pages en lugar de componentes de Razor para Identityinterfaz de usuario relacionada, como el registro de usuarios, el inicio de sesión, el cierre de sesión y otras tareas de administración de usuarios. La creación de componentes de Razor que controlan tareas de Identity directamente es posible en varios escenarios, pero Microsoft no lo recomienda ni admite.

Las abstracciones de ASP.NET Core, como SignInManager<TUser> y UserManager<TUser>, no se admiten en los componentes Razor. Para más información sobre el uso de Identity de ASP.NET Core con Blazor, vea Scaffolding de Identity de ASP.NET Core en una aplicación Blazor del lado servidor.

Nota:

En los ejemplos de código de este artículo se adoptan tipos de referencia que admiten un valor NULL (NRT) y análisis estático de estado NULL del compilador de .NET, que se admiten en ASP.NET Core en .NET 6 o posterior. Al tener como destino ASP.NET Core 5.0 o versiones anteriores, quite la designación de tipo null (?) de los ejemplos del artículo.

Compatibilidad con antiforgería

La plantilla Blazor:

El componente AntiforgeryToken representa un token de antifalsificación como un campo oculto y este componente se agrega automáticamente a las instancias de formulario (EditForm). Para obtener más información, vea Introducción a los formularios de ASP.NET CoreBlazor.

El servicio AntiforgeryStateProvider proporciona acceso a un token de antifalsificación asociado a la sesión actual. Inserte el servicio y llame a su método GetAntiforgeryToken() para obtener el valor AntiforgeryRequestTokenactual. Para obtener más información, vea Llamada a una API web desde una aplicación Blazor de ASP.NET Core.

Blazor almacena tokens de solicitud en estado de componente, lo que garantiza que los tokens de antifalsificación están disponibles para los componentes interactivos, incluso cuando no tienen acceso a la solicitud.

Nota:

La mitigación antiforgería solo es necesaria al enviar datos de formulario al servidor codificados como application/x-www-form-urlencoded, multipart/form-data, o text/plain, ya que son los únicos tipos de formulario válidos.

Para obtener más información, consulte los siguientes recursos:

Autenticación

Blazor usa los mecanismos de autenticación de ASP.NET Core existentes para establecer la identidad del usuario. El mecanismo exacto depende de cómo esté hospedada la aplicación Blazor, del lado servidor o del lado cliente.

Autenticación de Blazor del lado servidor

El Blazor del lado servidor representado de forma interactiva funciona a través de una conexión SignalR con el cliente. La autenticación en aplicaciones basadas en SignalR se controla cuando se establece la conexión. La autenticación se puede basar en una cookie o algún otro token de portador, pero la autenticación se administra a través del centro de SignalR y completamente dentro del circuito.

El servicio AuthenticationStateProvider integrado obtiene datos de estado de autenticación de HttpContext.User de ASP.NET Core. Así es como el estado de autenticación se integra con los mecanismos de autenticación de ASP.NET Core.

IHttpContextAccessor/HttpContext en Razor componentes

IHttpContextAccessor debe evitarse con la representación interactiva porque no hay un HttpContext válido disponible.

IHttpContextAccessor se puede usar para los componentes que se representan estáticamente en el servidor. Sin embargo, se recomienda evitarlo si es posible.

HttpContextse puede usar como parámetro en cascada solo en componentes raíz representados estáticamente para tareas generales, como inspeccionar y modificar encabezados u otras propiedades del componente App (Components/App.razor). El valor siempre es null para la representación interactiva.

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

En escenarios en los que se requiere el HttpContext en componentes interactivos, se recomienda hacer fluir los datos a través del estado del componente persistente desde el servidor. Para más información, veaOtros escenarios de seguridad de Blazor en ASP.NET Core del lado servidor.

No use IHttpContextAccessor/HttpContext directa o indirectamente en los componentes Razor de las aplicaciones Blazor del lado servidor. Las aplicaciones de Blazor se ejecutan fuera del contexto de la canalización de ASP.NET Core. No se garantiza que HttpContext esté disponible en IHttpContextAccessor, ni tampoco que HttpContext contenga el contexto que ha iniciado la aplicación de Blazor.

El enfoque recomendado para pasar el estado de solicitud a la aplicación de Blazor es a través de parámetros de componente raíz durante la representación inicial de la aplicación. Como alternativa, la aplicación puede copiar los datos en un servicio con ámbito en el evento de ciclo de vida de inicialización del componente raíz para usarlos en toda la aplicación. Para más información, veaOtros escenarios de seguridad de Blazor en ASP.NET Core del lado servidor.

Un aspecto crítico de la seguridad de Blazor del lado servidor es que el usuario asociado a un circuito determinado podría actualizarse en algún momento después de establecer el circuito de Blazor, pero IHttpContextAccessorno se actualiza. Para más información sobre cómo abordar esta situación con servicios personalizados, vea Otros escenarios de seguridad de Blazor en ASP.NET Core del lado servidor.

Estado compartido

Las aplicaciones Blazor del lado servidor residen en la memoria del servidor, y varias sesiones de aplicación se hospedan en el mismo proceso. Para cada sesión de aplicación, Blazor inicia un circuito con su propio ámbito de contenedor de inserción de dependencias, por lo que los servicios con ámbito son únicos para cada sesión de Blazor.

Advertencia

No se recomienda que las aplicaciones del mismo servidor compartan estado mediante servicios singleton, a menos que se tomen precauciones, ya que esto puede incorporar vulnerabilidades de seguridad, como la pérdida de estado de usuario entre circuitos.

Puede usar servicios singleton con estado en aplicaciones de Blazor si están específicamente diseñadas para ello. Por ejemplo, el uso de una caché de memoria singleton es aceptable porque una memoria caché requiere una clave para acceder a una entrada determinada. Suponiendo que los usuarios no tengan control sobre las claves de caché que se usan con la memoria caché, el estado almacenado en la memoria caché no se filtra entre circuitos.

Para obtener instrucciones generales sobre la administración de estados, consulte: Administración de estados de Blazor en ASP.NET Core.

Autenticación de Blazor del lado cliente

En las aplicaciones Blazor del lado cliente, las comprobaciones de autenticación se pueden omitir porque los usuarios pueden modificar todo el código del lado cliente. Lo mismo se aplica a todas las tecnologías de aplicaciones del lado cliente, incluidas las plataformas JavaScript SPA y las aplicaciones nativas para cualquier sistema operativo.

Agregue la siguiente línea de código:

Para controlar la autenticación, el uso del servicio integrado o personalizado de AuthenticationStateProvider se describe en las secciones siguientes.

Para más información, vea Protección de Blazor WebAssembly en ASP.NET Core.

Servicio AuthenticationStateProvider

AuthenticationStateProvider es el servicio subyacente utilizado por el componente AuthorizeView y los servicios de autenticación en cascada para obtener el estado de autenticación de un usuario.

AuthenticationStateProvider es el servicio subyacente utilizado por el componente AuthorizeView y el componente CascadingAuthenticationState para obtener el estado de autenticación de un usuario.

Por lo general, no se utiliza AuthenticationStateProvider directamente. Use los enfoques del componente AuthorizeView o Task<AuthenticationState> descritos más adelante en este artículo. El principal inconveniente de utilizar AuthenticationStateProvider directamente es que el componente no se notifica de manera automática si cambia el estado de autenticación subyacente de los datos.

El servicio AuthenticationStateProvider puede proporcionar los datos de ClaimsPrincipal del usuario actual, como se muestra en el ejemplo siguiente.

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

En el ejemplo anterior:

  • ClaimsPrincipal.Claims devuelve las notificaciones del usuario (claims) para mostrarlas en la interfaz de usuario.
  • La línea que obtiene el apellido del usuario (surname) llama a ClaimsPrincipal.FindAll con un predicado para filtrar las notificaciones del usuario.
@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.";
        }
    }
}

Si user.Identity.IsAuthenticated es true y porque el usuario es ClaimsPrincipal, se pueden enumerar las notificaciones y evaluar la pertenencia a roles.

Para más información sobre la inserción de dependencias (DI) y servicios, consulte Inserción de dependencias de Blazor de ASP.NET Core y Inserción de dependencias en ASP.NET Core. Para obtener información sobre cómo implementar una instancia de AuthenticationStateProvider personalizada en las aplicaciones Blazor del lado servidor, vea Protección de aplicaciones Blazor del lado servidor de ASP.NET Core.

Exposición del estado de autenticación como un parámetro en cascada

Si se requieren los datos de estado de autenticación para la lógica de procedimiento, como cuando se realiza una acción desencadenada por el usuario, obtenga los datos de estado de autenticación mediante la definición de un parámetro en cascada del tipo Task<AuthenticationState>, como se muestra en el ejemplo siguiente.

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

Si user.Identity.IsAuthenticated es true, se pueden enumerar las notificaciones y evaluar la pertenencia a roles.

Configure el Task<AuthenticationState>parámetro en cascada mediante los AuthorizeRouteView y los servicios de estado de autenticación en cascada.

Al crear una aplicación Blazor a partir de una de las plantillas de proyecto de Blazor con la autenticación habilitada, la aplicación incluye la llamada a AuthorizeRouteView y AddCascadingAuthenticationState que se muestran en el ejemplo siguiente. Una aplicación Blazor del lado cliente también incluye los registros de servicio necesarios. Se presenta información adicional en la sección Personalización del contenido no autorizado con el componente de enrutador.

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

En el archivo Program, registre los servicios de estado de autenticación en cascada:

builder.Services.AddCascadingAuthenticationState();

Configure el parámetro en cascadaTask<AuthenticationState> mediante los componentes AuthorizeRouteView y CascadingAuthenticationState.

Al crear una aplicación Blazor a partir de una de las plantillas de proyecto de Blazor con la autenticación habilitada, la aplicación incluye los componentes AuthorizeRouteView y CascadingAuthenticationState que se muestran en el ejemplo siguiente. Una aplicación Blazor del lado cliente también incluye los registros de servicio necesarios. Se presenta información adicional en la sección Personalización del contenido no autorizado con el componente de enrutador.

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

Nota:

Con la publicación de ASP.NET Core 5.0.1 y para las versiones 5.x adicionales, el componente Router incluye el parámetro PreferExactMatches establecido en @true. Para más información, vea Migración de ASP.NET Core 3.1 a 5.0.

En una aplicación Blazor del lado cliente, agregue servicios relativos a opciones y autorización al archivo Program:

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

En una aplicación Blazor del lado servidor, ya existen servicios para opciones y autorización, por lo que no es necesario adoptar otros pasos.

Autorización

Cuando un usuario está autenticado, se aplican las reglas de autorización para controlar qué puede hacer el usuario.

Por lo general, se concede o deniega el acceso en función de si:

  • El usuario está autenticado (ha iniciado sesión).
  • El usuario está en un rol.
  • El usuario tiene una notificación.
  • Una directiva se cumple.

Cada uno de estos conceptos tiene su equivalente en una aplicación ASP.NET Core MVC o Razor Pages. Para más información sobre la seguridad de ASP.NET Core, consulte los artículos disponibles en Seguridad e Identity de ASP.NET Core.

Componente de AuthorizeView

El componente AuthorizeView selectivamente muestra el contenido de la interfaz de usuario dependiendo de si el usuario tiene la autorización necesaria. Este enfoque es útil cuando solo necesite mostrar datos del usuario y no es necesario usar la identidad del usuario en la lógica de procedimientos.

El componente expone una variable context del tipo AuthenticationState (@context en sintaxis de Razor), que puede utilizar para acceder a la información sobre el usuario que ha iniciado sesión:

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

También puede proporcionar contenido diferente para mostrar si el usuario no está autorizado con una combinación de los parámetros Authorized y 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() { ... }
}

Solo los usuarios autorizados pueden invocar los controladores de eventos predeterminados de un elemento autorizado, como el método SecureMethod del elemento <button> que hay en el ejemplo anterior.

Los componentes Razor de aplicaciones web Blazor nunca muestran contenido <NotAuthorized> cuando se produce un error en la autorización del lado servidor durante la representación estática del lado servidor (SSR estático). La canalización ASP.NET Core del lado servidor procesa la autorización en el servidor. Use técnicas del lado servidor para controlar solicitudes no autorizadas. Para obtener más información, vea Modos de representación de ASP.NET CoreBlazor.

Advertencia

El marcado del lado cliente y los métodos asociados a AuthorizeView solo están protegidos de la visualización y la ejecución en la interfaz de usuario representada en aplicaciones Blazor del lado cliente. Para proteger el contenido autorizado y los métodos en Blazor del lado cliente, el contenido suele proporcionarse mediante una llamada API web segura y autorizada a una API de servidor y nunca se almacena en la aplicación. Para obtener más información, consulte Llamada a una API web desde una aplicación de ASP.NET Core Blazor y Otros escenarios de seguridad de Blazor WebAssembly en ASP.NET Core.

El contenido de Authorized y NotAuthorized puede incluir elementos arbitrarios, como otros componentes interactivos.

Las condiciones de autorización, como los roles o directivas que controlan las opciones o el acceso a la interfaz de usuario, se tratan en la sección Autorización.

Si no se especifican las condiciones de la autorización, AuthorizeView usa una directiva predeterminada:

  • Se autoriza a los usuarios autenticados (con sesión iniciada).
  • Se desautoriza a los usuarios no autenticados (sin sesión iniciada).

El componente AuthorizeView se puede usar en el componente NavMenu (Shared/NavMenu.razor) para mostrar un componente NavLink (NavLink), pero tenga en cuenta que este enfoque solo quita el elemento de lista de la salida representada. No impide que el usuario navegue hasta el componente. Implemente la autorización por separado en el componente de destino.

Autorización basada en roles y en directivas

El componente AuthorizeView admite la autorización basada en roles o basada en directivas.

Para la autorización basada en roles, utilice el parámetro Roles. En el ejemplo siguiente, el usuario debe tener una notificación de rol para el rol Admin o Superuser:

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

Para requerir que un usuario tenga notificaciones de rol de Admin y Superuser, anide 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>

El código anterior establece un valor Context para que el componente interno AuthorizeView evite una colisión de contexto AuthenticationState. Se accede al contexto AuthenticationState en el AuthorizeView exterior con el enfoque estándar para acceder al contexto (@context.User). Se accede al contexto en el AuthorizeView interior con el contexto innerContext con nombre (@innerContext.User).

Para más información, además de una guía de configuración, consulte Autorización basada en roles en ASP.NET Core.

Para la autorización basada en directivas, use el parámetro Policy con una sola directiva:

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

En caso de que el usuario deba cumplir una de varias directivas, cree una directiva que confirme que el usuario cumple otras directivas.

En caso de que el usuario deba cumplir varias directivas simultáneamente, adopte cualquiera de los métodos siguientes:

  • Cree una directiva para AuthorizeView que confirme que el usuario cumple otras directivas.

  • Anide las directivas en varios componentes AuthorizeView:

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

La autorización basada en notificaciones es un caso especial de autorización basada en directivas. Por ejemplo, puede definir una directiva que requiere que los usuarios tengan una notificación determinada. Para obtener más información, vea Autorización basada en directivas en ASP.NET Core.

Si no se especifica Roles ni Policy, AuthorizeView usa la directiva predeterminada:

  • Se autoriza a los usuarios autenticados (con sesión iniciada).
  • Se desautoriza a los usuarios no autenticados (sin sesión iniciada).

Dado que las comparaciones de cadenas de .NET distinguen mayúsculas de minúsculas de forma predeterminada, los nombres de rol y directiva coincidentes también distinguen mayúsculas de minúsculas. Por ejemplo, Admin (A mayúscula) no se trata como el mismo rol que admin (a minúscula).

Normalmente se usa la notación Pascal para los nombres de rol y directiva (por ejemplo, BillingAdministrator), pero el uso de esta notación no es un requisito estricto. Se permiten diferentes notaciones, como la grafía camel, la grafía kebab y la grafía de serpiente (distintos tipos de uso de mayúsculas y minúsculas y separaciones con guiones). El uso de espacios en nombres de roles y directivas es inusual, pero lo permite el marco. Por ejemplo, billing administrator es un formato inusual de nombre de directiva o rol en aplicaciones de .NET, pero es un nombre de directiva o rol válido.

Contenido que se muestra durante la autenticación asincrónica

Blazor permite que el estado de autenticación se determine asincrónicamente. El escenario principal para este enfoque se encuentra en las aplicaciones Blazor del lado cliente que realizan una solicitud a un punto de conexión externo para la autenticación.

Mientras la autenticación está en curso, AuthorizeView no muestra ningún contenido de forma predeterminada. Para mostrar el contenido mientras se produce la autenticación, asigne contenido al 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>

Este enfoque no se aplica normalmente a las aplicaciones Blazor del lado servidor. Las aplicaciones Blazor del lado servidor conocen el estado de autenticación tan pronto como se establece ese estado. El contenido de Authorizing se puede proporcionar en un componente AuthorizeView de una aplicación, pero nunca se muestra.

Atributo [Authorize]

El atributo [Authorize] está disponible en los componentes Razor:

@page "/"
@attribute [Authorize]

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

Importante

Utilice únicamente [Authorize] en componentes @page a los que se llega a través del enrutador de Blazor. La autorización solo se realiza como un aspecto del enrutamiento y no para los componentes secundarios representados dentro de una página. Para autorizar la presentación de partes concretas dentro de una página, use AuthorizeView en su lugar.

El atributo [Authorize] admite también la autorización basada en roles o basada en directivas. Para la autorización basada en roles, utilice el 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 la autorización basada en directivas, utilice el parámetro Policy:

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

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

Si no se especifica Roles ni Policy, [Authorize] usa la directiva predeterminada:

  • Se autoriza a los usuarios autenticados (con sesión iniciada).
  • Se desautoriza a los usuarios no autenticados (sin sesión iniciada).

Cuando el usuario no está autorizado y si la aplicación no personaliza contenido no autorizado con el componente de enrutador, el marco muestra automáticamente el siguiente mensaje de reserva:

Not authorized.

Autorización de recursos

Para autorizar a los usuarios para los recursos, pase los datos de ruta de la solicitud al parámetro Resource de AuthorizeRouteView.

En el contenido de Router.Found de una ruta solicitada:

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

Para obtener más información sobre cómo se pasan los datos de estado de autorización y cómo se usan en la lógica de procedimientos, consulte la sección Exposición del estado de autenticación como parámetro en cascada.

Cuando la AuthorizeRouteView recibe los datos de ruta del recurso, las directivas de autorización tienen acceso RouteData.PageType a y RouteData.RouteValues que permiten que la lógica personalizada tome decisiones de autorización.

En el ejemplo siguiente, se crea una directiva EditUser en AuthorizationOptions para la configuración del servicio de autorización de la aplicación (AddAuthorizationCore) con la lógica siguiente:

  • Determine si existe un valor de ruta con una clave de id. Si la clave existe, el valor de ruta se almacena en value.
  • En una variable denominada id, almacene value como una cadena o establezca un valor de cadena vacío (string.Empty).
  • Si id no es una cadena vacía, aserte que la directiva se cumple (devuelve true) si el valor de la cadena comienza por EMP. De lo contrario, aserte que se produce un error en la directiva (devuelve false).

En el archivo Program:

  • Agregue espacios de nombres de Microsoft.AspNetCore.Components y System.Linq:

    using Microsoft.AspNetCore.Components;
    using System.Linq;
    
  • Agregue la directiva:

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

El ejemplo anterior es una directiva de autorización sobreimplificada, que simplemente se usa para demostrar el concepto con un ejemplo práctico. Para obtener más información sobre la creación y configuración de directivas de autorización, vea Autorización basada en directivas en ASP.NET Core.

En el componente EditUser siguiente, el recurso en /users/{id}/edit tiene un parámetro de ruta para el identificador del usuario ({id}). El componente usa la directiva de autorización EditUser anterior para determinar si el valor de ruta de id comienza por EMP. Si id comienza por EMP, la directiva se aplica correctamente y se autoriza el acceso al componente. Si id comienza con un valor distinto de EMP o si id es una cadena vacía, se produce un error en la directiva y el componente no se carga.

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

Personalización del contenido no autorizado con el componente de enrutador

El componente Router, junto con el componente AuthorizeRouteView, permite que la aplicación especifique el contenido personalizado si:

  • El usuario produce un error en la condición [Authorize] aplicada al componente. Se muestra el marcado del elemento <NotAuthorized>. El atributo [Authorize] se describe en la sección Atributo [Authorize].
  • La autorización asincrónica está en curso, lo que normalmente significa que el proceso de autenticación del usuario está en curso. Se muestra el marcado del elemento <Authorizing>.

Importante

Las características de enrutador Blazor que muestran el contenido <NotAuthorized> y <NotFound> no están operativas durante la representación estática del lado servidor (SSR estático) porque el procesamiento de solicitudes se controla completamente mediante el procesamiento de solicitudes de canalización de middleware de ASP.NET y los componentes Razor no se representan para solicitudes no autorizadas o incorrectas. Use técnicas del lado servidor para controlar solicitudes no autorizadas e incorrectas durante el SSR estático. Para obtener más información, vea Modos de representación de ASP.NET CoreBlazor.

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

El contenido de Authorized y NotAuthorized puede incluir elementos arbitrarios, como otros componentes interactivos.

Nota:

El anterior requiere el registro de servicios de estado de autenticación en cascada en el archivo Program de la aplicación:

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

El contenido de NotFound, Authorized y NotAuthorized puede incluir elementos arbitrarios, como otros componentes interactivos.

Si no se especifica el contenido NotAuthorized, el AuthorizeRouteView usa el siguiente mensaje de reserva:

Not authorized.

Una aplicación creada a partir de la plantilla de proyecto de Blazor WebAssembly con la autenticación habilitada incluye un componente RedirectToLogin, que se coloca en el contenido <NotAuthorized> del componente Router. Cuando un usuario no está autenticado (context.User.Identity?.IsAuthenticated != true), el componente RedirectToLogin redirige el explorador al punto de conexión authentication/login para la autenticación. El usuario se devuelve a la dirección URL solicitada después de la autenticación con el proveedor de identidades.

Lógica de procedimientos

Si se requiere que la aplicación compruebe las reglas de autorización como parte de la lógica de procedimiento, utilice un parámetro en cascada del tipo Task<AuthenticationState> para obtener el ClaimsPrincipal del usuario. Task<AuthenticationState> se puede combinar con otros servicios, como IAuthorizationService, para evaluar las directivas.

En el ejemplo siguiente:

  • El user.Identity.IsAuthenticated ejecuta código para los usuarios autenticados (con sesión iniciada).
  • El user.IsInRole("admin") ejecuta código para los usuarios en el rol "Administrador".
  • El (await AuthorizationService.AuthorizeAsync(user, "content-editor")).Succeeded ejecuta código para los usuarios que satisfacen la directiva "content-editor".

Una aplicación Blazor del lado servidor incluye los espacios de nombres adecuados de forma predeterminada al crearse a partir de la plantilla de proyecto. En una aplicación Blazor del lado cliente, confirme la presencia de los espacios de nombres Microsoft.AspNetCore.Authorization y Microsoft.AspNetCore.Components.Authorization en el componente o en el archivo de la aplicación _Imports.razor:

@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

Errores comunes:

  • La autorización requiere un parámetro en cascada de tipo Task<AuthenticationState>. Considere la posibilidad de usar CascadingAuthenticationState para proporcionarlo.

  • Se recibe el valor null para authenticationStateTask

Es probable que el proyecto no se haya creado mediante una plantilla de Blazor del lado servidor con la autenticación habilitada.

En .NET 7 o versiones anteriores, encapsule una instancia de <CascadingAuthenticationState> en alguna parte del árbol de la interfaz, por ejemplo, en el enrutador Blazor:

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

En .NET 8 o versiones posteriores, no use el componente CascadingAuthenticationState:

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

En su lugar, agregue servicios de estado de autenticación en cascada a la colección de servicios del archivo Program:

builder.Services.AddCascadingAuthenticationState();

El componente CascadingAuthenticationState (.NET 7 o versiones anteriores) o los servicios proporcionados por AddCascadingAuthenticationState (.NET 8 o versiones posterior) proporcionan el parámetro Task<AuthenticationState> en cascada, que a su vez recibe del servicio de inserción AuthenticationStateProvider de dependencias subyacente.

Información de identificación personal

Microsoft usa la definición del RGPD para "datos personales" (RGPD 4.1) cuando la documentación describe información de identificación personal (PII).

LA PII hace referencia a cualquier información relacionada con una persona física identificada o identificable. Una persona física identificable es aquella que se puede identificar, directa o indirectamente, con cualquiera de las siguientes opciones:

  • Nombre
  • Número de identificación
  • Coordenadas de ubicación
  • Identificador en línea
  • Otros factores específicos
    • Físico
    • Fisiológica
    • Genética
    • Mental (psicológico)
    • Económico
    • Cultural
    • Identidad social

Recursos adicionales