Compartir a través de


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 de .NET 9 de este artículo.

Advertencia

Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulte la directiva de compatibilidad de .NET y .NET Core. Para la versión actual, consulte la versión de .NET 9 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 de .NET 9 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.

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.

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. Construye un Blazor Web App que solo se base en la representación del lado del servidor (SSR) para las comprobaciones de autorización y la aplicación de reglas.

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.

Razor Las convenciones de autorización de Pages no se aplican a los componentes de Razorenrutables. Si un componente Razor no enrutable está incorporado en una página de una aplicación de páginas de Razor, las convenciones de autorización de la página afectan indirectamente al componente Razor, así como 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 cliente-servidor de una 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 obtener más información sobre el uso de ASP.NET Core Identity con Blazor, vea Estructurar ASP.NET Core Identity en una aplicación Blazor del lado del 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.

Mantener de forma segura la información confidencial y las credenciales

No almacene secretos de aplicación, cadena de conexión, credenciales, contraseñas, números de identificación personal (PIN), código .NET/C# privado o claves o tokens privados en código del lado cliente, lo que siempre es inseguro. El código del lado Blazor cliente debe acceder a servicios y bases de datos seguros a través de una API web segura que controle.

En entornos de prueba/ensayo y producción, el código del lado Blazor servidor y las API web deben usar flujos de autenticación seguros que eviten mantener las credenciales dentro del código del proyecto o los archivos de configuración. Fuera de las pruebas de desarrollo local, se recomienda evitar el uso de variables de entorno para almacenar datos confidenciales, ya que las variables de entorno no son el enfoque más seguro. Para las pruebas de desarrollo local, se recomienda la herramienta Secret Manager para proteger los datos confidenciales. Para obtener más información, consulte los siguientes recursos:

Para el desarrollo y las pruebas locales del lado cliente y del lado servidor, use la herramienta Administrador de secretos para proteger las credenciales confidenciales.

Identidades administradas para servicios de Microsoft Azure

Para los servicios de Microsoft Azure, se recomienda usar identidades administradas. Las identidades administradas proporcionan una autenticación segura en los servicios de Azure sin almacenar credenciales en el código de la aplicación. Para obtener más información, consulte los siguientes recursos:

Soporte de antifalsificación

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 del lado del servidor Blazor

Las aplicaciones de Blazor del lado servidor están configuradas para la seguridad, de la misma manera que las aplicaciones ASP.NET Core. Para obtener más información, consulte los artículos disponibles en Temas de seguridad de ASP.NET Core.

El contexto de autenticación solo se establece cuando se inicia la aplicación, que es cuando la aplicación se conecta por primera vez a WebSocket a través de una SignalR conexión con el cliente. 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 contexto de la autenticación se mantiene durante la vigencia del circuito. Las aplicaciones vuelven a validar periódicamente el estado de autenticación del usuario cada 30 minutos.

Si la aplicación debe capturar usuarios para servicios personalizados o reaccionar a las actualizaciones del usuario, consulte ASP.NET Core del lado servidor y Blazor Web App.

Blazor difiere de una aplicación web representada por el servidor tradicional que realiza nuevas solicitudes HTTP con cookies en cada navegación de página. La autenticación se comprueba durante los eventos de navegación. Sin embargo, no se tienen en cuenta las cookies. Las cookies solo se envían al realizar una solicitud HTTP a un servidor, lo cual no sucede cuando el usuario navega en una aplicación de Blazor. Durante la navegación, el estado de autenticación del usuario se comprueba dentro de la carpeta Blazor que puede actualizar en cualquier momento en el servidor mediante la función RevalidatingAuthenticationStateProvider abstracción.

Importante

No se recomienda implementar un NavigationManager personalizado para lograr la validación de autenticación durante la navegación. Si la aplicación debe ejecutar la lógica de estado de autenticación personalizada durante la navegación, use un AuthenticationStateProvider personalizado.

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.

El servicio integrado o personalizado AuthenticationStateProvider 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.

Para obtener más información sobre la autenticación del lado servidor, consulte autenticación y autorización de ASP.NET CoreBlazor.

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.

Seguridad del lado servidor de datos confidenciales y credenciales

En entornos de prueba/ensayo y producción, el código del lado Blazor servidor y las API web deben usar flujos de autenticación seguros que eviten mantener las credenciales dentro del código del proyecto o los archivos de configuración. Fuera de las pruebas de desarrollo local, se recomienda evitar el uso de variables de entorno para almacenar datos confidenciales, ya que las variables de entorno no son el enfoque más seguro. Para las pruebas de desarrollo local, se recomienda la herramienta Secret Manager para proteger los datos confidenciales. Para obtener más información, consulte los siguientes recursos:

Para el desarrollo y las pruebas locales del lado cliente y del lado servidor, use la herramienta Administrador de secretos para proteger las credenciales confidenciales.

Plantilla de proyectos

Cree una nueva aplicación Blazor del lado servidor siguiendo las instrucciones de las Herramientas para ASP.NET Core Blazor.

Después de elegir la plantilla de aplicación del lado servidor y configurar el proyecto, seleccione la autenticación de la aplicación en Tipo de autenticación:

  • Ninguno (predeterminado): no hay autenticación.
  • Cuentas individuales: las cuentas de usuario se almacenan en la aplicación mediante Identity en ASP.NET Core.
  • Ninguno (predeterminado): no hay autenticación.
  • Cuentas individuales: las cuentas de usuario se almacenan en la aplicación mediante Identity en ASP.NET Core.
  • Plataforma de identidad de Microsoft: para más información, consulte Autenticación y autorización de Blazor en ASP.NET Core.
  • Windows: use la autenticación de Windows.

Blazor IdentityUI de (cuentas individuales)

Blazor admite la generación de una interfaz de usuario completa basada en BlazorIdentity al elegir la opción de autenticación para cuentas individuales.

La plantilla de Blazor Web App sirve de andamiaje para el código de Identity para una base de datos de SQL Server. La versión de la línea de comandos usa SQLite e incluye una base de datos de SQLite para Identity.

La plantilla :

  • Admite escenarios de representación interactiva del lado servidor (SSR interactiva) y representación del lado cliente (CSR) con usuarios autenticados.
  • Agrega componentes de IdentityRazor y lógica relacionada para tareas de autenticación rutinarias, como iniciar y cerrar sesión de usuarios. Los componentes de Identity también admiten características de Identity avanzadas, como confirmación de cuenta y recuperación de contraseña y autenticación multifactor mediante una aplicación de terceros. Ten en cuenta que los propios componentes de Identity no admiten interactividad.
  • Agrega los paquetes y dependencias relacionados con Identity.
  • Hace referencia a los paquetes de Identity en _Imports.razor.
  • Crea una clase de usuario Identity personalizada (ApplicationUser).
  • Crea y registra un contexto de base de datos EF Core (ApplicationDbContext).
  • Configura el enrutamiento para los puntos de conexión integrados Identity.
  • Incluye validación y lógica de negocios de Identity.

Para inspeccionar los componentes Blazor del marco Identity, accede a ellos en las carpetas Pages y Shared de la carpeta Account de la plantilla de proyecto Blazor Web App (origen de referencia).

Al elegir los modos de representación Interactive WebAssembly o Interactive Auto, el servidor gestiona todas las solicitudes de autenticación y autorización, y los componentes de Identity son representados estáticamente en el servidor dentro del proyecto principal de Blazor Web App.

El marco proporciona un AuthenticationStateProvider personalizado en los proyectos de servidor y cliente (.Client) para hacer que fluya el estado de autenticación del usuario al explorador. El proyecto de servidor llama a AddAuthenticationStateSerialization, mientras que el proyecto cliente llama a AddAuthenticationStateDeserialization. La autenticación en el servidor en lugar del cliente permite que la aplicación acceda al estado de autenticación durante la representación previa y antes de que se inicialice el runtime de WebAssembly de .NET. Las implementaciones personalizadas de AuthenticationStateProvider usan el servicio de estado de componente persistente (PersistentComponentState) para serializar el estado de autenticación en comentarios HTML y, después, volverlo a leer desde WebAssembly para crear una instancia de AuthenticationState. Para obtener más información, consulta la sección Gestionar el estado de autenticación en Blazor Web Apps.

Sólo para soluciones de Servidor Interactivo, IdentityRevalidatingAuthenticationStateProvider (fuente de referencia) es un servidor AuthenticationStateProvider que revalida el sello de seguridad para el usuario conectado cada 30 minutos que un circuito interactivo está conectado.

Al elegir los modos de representación de WebAssembly interactivo o Auto interactivo, el servidor controla todas las solicitudes de autenticación y autorización, y los componentes de Identity se representan estáticamente en el servidor dentro del proyecto principal de Blazor Web App. La plantilla de proyecto incluye una clase PersistentAuthenticationStateProvider (origen de referencia) en el proyecto .Client para sincronizar el estado de autenticación del usuario entre el servidor y el explorador. La clase es una implementación personalizada de AuthenticationStateProvider. El proveedor usa el servicio de estado de componente persistente (PersistentComponentState) para representar previamente el estado de autenticación y conservarlo en la página.

En el proyecto principal de Blazor Web App, el proveedor de estado de autenticación se denomina IdentityRevalidatingAuthenticationStateProvider (origen de referencia) (solo soluciones de interactividad de servidor) o PersistingRevalidatingAuthenticationStateProvider (origen de referencia) (soluciones de interactividad de WebAssembly o interactividad automática).

BlazorIdentity depende de instancias DbContext no creadas por una fábrica, lo que es intencional porque DbContext es suficiente para que los componentes Identity de la plantilla del proyecto se representen estáticamente sin soportar la interactividad.

Para obtener una descripción de cómo se aplican los modos de representación interactiva global a los componentes que no son componentes Identity, mientras que al mismo tiempo se aplica SSR estático a los componentes Identity, consulte ASP.NET Core Blazor modos de representación.

Para obtener más información sobre cómo conservar el estado prerrepresentado, consulte Prerrepresentar componentes Razor ASP.NET Core.

Nota

Los vínculos de la documentación al origen de referencia de .NET cargan normalmente la rama predeterminada del repositorio, que representa el desarrollo actual para la próxima versión de .NET. Para seleccionar una etiqueta de una versión específica, usa la lista desplegable Cambiar ramas o etiquetas. Para obtener más información, consulta Procedimientos para seleccionar una etiqueta de versión de código fuente de ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Administrar el estado de la autenticación en Blazor Web App

Esta sección se aplica a Blazor Web App que adoptan:

  • Cuentas individuales
  • Representación del lado cliente (CSR, interactividad basada en WebAssembly).

Un proveedor de estado de autenticación del lado cliente solo se usa en Blazor y no está integrado con el sistema de autenticación ASP.NET Core. Durante la representación previa, Blazor respeta los metadatos definidos en la página y usa el sistema de autenticación ASP.NET Core para determinar si el usuario está autenticado. Cuando un usuario navega de una página a otra, se usa un proveedor de autenticación del lado cliente. Cuando el usuario actualiza la página (recarga de página completa), el proveedor de estado de autenticación del lado cliente no participa en la decisión de autenticación en el servidor. Dado que el servidor no conserva el estado del usuario, se pierde ningún estado de autenticación mantenido en el lado cliente.

Para solucionar esto, el mejor enfoque es realizar la autenticación en el sistema de autenticación ASP.NET Core. El proveedor de estado de autenticación del lado cliente solo se encarga de reflejar el estado de autenticación del usuario. Los ejemplos de cómo hacerlo con proveedores de estado de autenticación se muestran mediante la plantilla de proyecto de Blazor Web App y se describen a continuación.

En el archivo Program del proyecto de servidor, llame a AddAuthenticationStateSerialization, que serializa la AuthenticationState devuelta por el AuthenticationStateProvider del lado servidor mediante el servicio estado de componente persistente (PersistentComponentState):

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

La API solo serializa las declaraciones de nombre y rol del lado del servidor para acceder en el navegador. Para incluir todas las notificaciones, establezca SerializeAllClaims en true en la llamada del lado servidor a AddAuthenticationStateSerialization:

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

En el archivoProgram del proyecto del cliente (.Client), llame a AddAuthenticationStateDeserialization, que agrega un AuthenticationStateProvider en el que el AuthenticationState se deserializa desde el servidor mediante AuthenticationStateData y el servicio de estado de componente persistente (PersistentComponentState). Debe haber una llamada correspondiente a AddAuthenticationStateSerialization en el proyecto de servidor.

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

Nota

Los vínculos de la documentación al origen de referencia de .NET cargan normalmente la rama predeterminada del repositorio, que representa el desarrollo actual para la próxima versión de .NET. Para seleccionar una etiqueta de una versión específica, usa la lista desplegable Cambiar ramas o etiquetas. Para obtener más información, consulta Procedimientos para seleccionar una etiqueta de versión de código fuente de ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Scaffolding para Identity

Para obtener más información sobre scaffolding de Identity en un proyecto de aplicación Blazor del lado servidor, consulte Scaffolding de Identity en proyectos de ASP.NET Core.

Scaffolding de Identity a una aplicación de Blazor del lado servidor:

Reclamaciones y tokens adicionales de proveedores externos

Para almacenar notificaciones adicionales de proveedores externos, consulte Conservar notificaciones y tokens adicionales en in ASP.NET Core.

Azure App Service en Linux con Identity Server

Al realizar una implementación en Azure App Service en Linux con Identity Server, especifique el emisor de forma explícita. Para más información, consulte Uso de Identity para proteger un back-end de API web para SPA.

Inserción del AuthenticationStateProvider para los servicios con ámbito en un componente

No intente resolver AuthenticationStateProvider dentro de un ámbito personalizado porque dará como resultado la creación de una nueva instancia del AuthenticationStateProvider que no se inicializa correctamente.

Para acceder al AuthenticationStateProvider dentro de un servicio con ámbito a un componente, inyecte el AuthenticationStateProvider en el componente y páselo al servicio como parámetro. Este enfoque garantiza que la instancia correcta e inicializada del AuthenticationStateProvider se use para cada instancia de aplicación de usuario.

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 el servicio como uno con ámbito. En una aplicación del lado servidor de Blazor, los servicios con ámbito tienen una vigencia igual a la duración del circuito de la conexión de cliente.

En el archivo Program:

builder.Services.AddScoped<ExampleService>();

En Startup.ConfigureServices de Startup.cs:

services.AddScoped<ExampleService>();

En el componente InjectAuthStateProvider siguiente:

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 más información, consulte las instrucciones de OwningComponentBase en la Inserción de dependencias de Blazor en ASP.NET Core.

Visualización de contenido no autorizado durante la representación previa con un AuthenticationStateProvider personalizado

Para evitar mostrar contenido no autorizado, por ejemplo contenido en un componente AuthorizeView, mientras se representa previamente con un elemento AuthenticationStateProvider personalizado, adopte uno de los enfoques siguientes:

  • Deshabilite la representación previa: indique el modo de representación con el parámetro prerender establecido en false en el componente de nivel más alto de la jerarquía de componentes de la aplicación que no sea un componente raíz.

    Nota

    No se admite la creación de un componente raíz interactivo, como el componente App. Por lo tanto, el componente App no puede deshabilitar la representación previa directamente.

    En el caso de las aplicaciones basadas en la plantilla de proyecto de Blazor Web App, la representación previa se deshabilita normalmente cuando se usa el componente Routes en el componente App (Components/App.razor):

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

    Además, deshabilite la representación previa para el componente de HeadOutlet:

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

    También puede controlar de forma selectiva el modo de representación aplicado a la instancia del componente Routes. Por ejemplo, consulte los modos de representación de ASP.NET Core Blazor.

  • Autenticar al usuario en el servidor antes de que se inicie la aplicación: para adoptar este enfoque, la aplicación debe responder a la solicitud inicial de un usuario con la página o vista de inicio de sesión basada en Identity y evitar las solicitudes a puntos de conexión Blazor hasta que se autentiquen. Para más información, consulte Creación de una aplicación ASP.NET Core con datos de usuario protegidos por autorización. Después de la autenticación, solo se muestra contenido no autorizado en componentes de Razor creados previamente cuando el usuario no está autorizado para ver el contenido.

Administración de estados de usuario

A pesar de contener la palabra "state" (estado) en el nombre, AuthenticationStateProvider no se usa para almacenar el estado del usuario general. AuthenticationStateProvider indica únicamente el estado de autenticación del usuario a la aplicación, si ha iniciado sesión en ella y el nombre de usuario con el que ha iniciado sesión.

La autenticación usa la misma autenticación ASP.NET Core Identity que Razor Pages y las aplicaciones MVC. El estado de usuario almacenado en la Identity de ASP.NET Core se transfiere a Blazor sin necesidad de añadir código adicional a la aplicación. Siga las instrucciones de los artículos y tutoriales de ASP.NET Core Identity para que las funcionalidades de Identity tengan efecto en las partes Blazor de la aplicación.

Para orientación sobre la administración de estado general fuera de ASP.NET Core Identity, consulte Administración de estado de Blazor en ASP.NET Core.

Abstracciones de seguridad adicionales

Dos abstracciones adicionales participan en la administración del estado de autenticación:

Nota

Los vínculos de la documentación al origen de referencia de .NET cargan normalmente la rama predeterminada del repositorio, que representa el desarrollo actual para la próxima versión de .NET. Para seleccionar una etiqueta de una versión específica, usa la lista desplegable Cambiar ramas o etiquetas. Para obtener más información, consulta Procedimientos para seleccionar una etiqueta de versión de código fuente de ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Administración del estado de autenticación al cerrar sesión

El Blazor del lado servidor conserva el estado de autenticación del usuario durante la vigencia del circuito, incluidas las pestañas del explorador. Para cerrar la sesión proactiva de un usuario en las pestañas del explorador cuando el usuario cierra sesión en una pestaña, debes implementar un elemento RevalidatingServerAuthenticationStateProvider (origen de referencia) con un elemento RevalidationInterval corto.

Nota

Los vínculos de la documentación al origen de referencia de .NET cargan normalmente la rama predeterminada del repositorio, que representa el desarrollo actual para la próxima versión de .NET. Para seleccionar una etiqueta de una versión específica, usa la lista desplegable Cambiar ramas o etiquetas. Para obtener más información, consulta Procedimientos para seleccionar una etiqueta de versión de código fuente de ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Duración de la validez de la dirección URL de redireccionamiento temporal

Esta sección es aplicable a Blazor Web App.

Usa la opción RazorComponentsServiceOptions.TemporaryRedirectionUrlValidityDuration para obtener o establecer la vigencia de la validez de la protección de datos de ASP.NET Core para las direcciones URL de redirección temporales emitidas por la representación del lado servidor Blazor. Solo se usan transitoriamente, por lo que la duración debe simplemente ser lo suficientemente larga como para que un cliente reciba la dirección URL y comience la navegación a ella. Sin embargo, también debe ser lo suficientemente larga como para permitir el desfase de reloj entre servidores. El valor predeterminado es cinco minutos.

En el ejemplo siguiente, el valor se extiende a siete minutos:

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

Autenticación del lado del cliente Blazor

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, usa el servicio AuthenticationStateProvider integrado o personalizado.

Para obtener más información sobre la autenticación del lado cliente, consulta Secure ASP.NET Core Blazor WebAssembly.

Protección de datos en Blazor Web Apps con representación automática interactiva

Cuando un Blazor Web App adopta la representación del lado servidor (SSR) y la representación del lado cliente (CSR) para componentes o una aplicación completa que especifica el modo de representación automática interactiva , la autorización para acceder a componentes y datos se aplica en dos lugares. El componente restringe el acceso a sí mismo (y los datos que obtiene) cuando se representan en el servidor en virtud de un atributo de autorización en el archivo de definición del componente (@attribute [Authorize]). Cuando el componente se representa en el cliente, el acceso a los datos se restringe a través de los puntos de conexión de la API web del servidor a los que se llama desde el cliente. Se debe tener cuidado al proteger el acceso a los datos en ambas ubicaciones para evitar el acceso incorrecto a los datos.

Considere el siguiente escenario en el que un componente muestra los datos meteorológicos seguros. El ejemplo siguiente se puede examinar y mostrar en una aplicación de ejemplo en ejecución con el ejemplo de BlazorWebAppEntra (.NET 9 o posterior) o el ejemplo de BlazorWebAppOidc (.NET 8 o posterior) en el repositorio de GitHub de ejemplos de Blazor (dotnet/blazor-samples) (cómo descargar).

El proyecto cliente mantiene una clase WeatherForecast para contener datos meteorológicos:

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

La interfaz IWeatherForecaster del proyecto cliente define un método GetWeatherForecastAsync para obtener datos meteorológicos:

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

El servicio ClientWeatherForecaster del proyecto cliente implementa IWeatherForecaster. El método GetWeatherForecastAsync llama a una API web en el proyecto del servidor en el punto final /weather-forecast para obtener datos meteorológicos.

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

El proyecto cliente mantiene un componente de Weather que:

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

<PageTitle>Weather</PageTitle>

<h1>Weather</h1>

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

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

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

    protected override async Task OnInitializedAsync()
    {
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);

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

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

        return Task.CompletedTask;
    }

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

El proyecto de servidor implementa IWeatherForecaster como ServerWeatherForecaster, que genera y devuelve datos meteorológicos ficticios a través de su método GetWeatherForecastAsync:

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

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

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

El proyecto de servidor mantiene un punto de conexión seguro de API web para las llamadas a datos meteorológicos destinados a clientes.

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

Con el enfoque anterior, hay dos sistemas implementados para proporcionar datos meteorológicos seguros al usuario:

  • Cuando el componente Weather se representa en el servidor, el método GetWeatherForecastAsync del servicio ServerWeatherForecaster se usa directamente para obtener los datos meteorológicos. La seguridad de los datos se aplica mediante el atributo [Authorize] del componente. En resumen, la seguridad de los datos meteorológicos se garantiza mediante el componente.
  • Cuando el componente Weather se representa en el cliente, el servicio ClientWeatherForecaster se usa para realizar una llamada API web al punto de conexión seguro de /weather-forecast que aplica el método de extensión RequireAuthorization. Si el usuario tiene la autoridad para acceder a los datos meteorológicos, el punto de conexión usa el servicio ServerWeatherForecaster para llamar a GetWeatherForecastAsync. Los datos se devuelven al cliente. En resumen, el punto de conexión de la API web del servidor garantiza la seguridad de los datos meteorológicos.

El enfoque anterior funciona bien cuando los requisitos de seguridad de la API web coinciden con los requisitos de seguridad del componente. Por ejemplo, la misma directiva de autorización se puede aplicar al punto de conexión de la API web y al componente.

Los escenarios complejos requieren planeación e implementación adicionales. Por ejemplo, una API web de servidor que tiene varios autores de llamadas con permisos de acceso diferentes requiere una directiva de autorización más sofisticada, una o varias directivas adicionales o puntos de conexión adicionales con requisitos de acceso diferentes.

A medida que incorpora medidas de seguridad en las aplicaciones que adoptan el rendimiento automático interactivo, tenga en cuenta que la seguridad implementada para los puntos de conexión de la API web del servidor no protege la implementación del servicio del servidor, que se utiliza cuando se renderiza un componente en el servidor y accede a los datos a través del servicio. Pondera cuidadosamente la diferencia entre el acceso a los datos en el servidor durante el SSR y el acceso a los datos en una solicitud de API web cliente durante la CSR. Aplique estratégicamente la seguridad para evitar el acceso incorrecto a los datos.

Ejemplos en el repositorio de GitHub de ejemplos de Blazor (dotnet/blazor-samples) (cómo descargar) que muestran el enfoque descrito en esta sección:

  • BlazorWebAppOidc
  • BlazorWebAppOidcBff
  • BlazorWebAppEntra

AuthenticationStateProvider Servicio

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. Utilice el componente AuthorizeView o los enfoques 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.

Para implementar un AuthenticationStateProvider personalizado, consulta ASP.NET Core Blazorestado de autenticación, que incluye una guía sobre la implementación de notificaciones de cambio de estado de autenticación de usuario.

Obtención de los datos del principal de una declaración de usuario

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

ClaimsPrincipalData.razor:

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

<h1>ClaimsPrincipal Data</h1>

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

<p>@authMessage</p>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@surname</p>

@code {
    private string? authMessage;
    private string? surname;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

En el ejemplo anterior:

  • ClaimsPrincipal.Claims devuelve las declaraciones 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 afirmaciones del usuario.
@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

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

<p>@authMessage</p>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@surname</p>

@code {
    private string? authMessage;
    private string? surname;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

Si user.Identity.IsAuthenticated es true y debido a que el usuario es ClaimsPrincipal, se pueden enumerar las reclamaciones y evaluar la pertenencia a los 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 un AuthenticationStateProvider personalizado, consulta ASP.NET Core Blazor estado de autenticación.

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 afirmaciones y evaluar la pertenencia en 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. Aquí se presenta información adicional Personalizar el contenido no autorizado con el Router componente sección.

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

Configura el Task<AuthenticationState>parámetro en cascada utilizando 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. Aquí se presenta información adicional Personalizar el contenido no autorizado con el Router componente sección.

<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 de autorización al archivo Program:

builder.Services.AddAuthorizationCore();

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

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

Aunque el AuthorizeView componente controla la visibilidad de los elementos en función del estado de autorización del usuario, no aplica la seguridad en el propio controlador de eventos. En el ejemplo anterior, el HandleClick método solo está asociado a un botón visible para los usuarios autorizados, pero nada impide invocar este método desde otros lugares. Para garantizar la seguridad de nivel de método, implemente lógica de autorización adicional dentro del propio controlador o en la API pertinente.

Los componentes Razor de Blazor Web App nunca muestran contenido <NotAuthorized> cuando se produce un error de autorización del lado servidor durante la representación estática del lado servidor (SSR estática). 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 seguros en Blazor del lado del cliente, el contenido suele proporcionarse mediante una llamada 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 considera no autorizados a los usuarios no autenticados (cerraron sesión).

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 declaración de rol para los roles 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 Policy parámetro con un nombre de directiva único:

<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 reclamaciones es un caso especial de autorización basada en directivas. Por ejemplo, puede definir una directiva que requiera que los usuarios tengan una afirmació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:

  • Los usuarios autenticados (iniciados sesión) están autorizados.
  • Los usuarios no autenticados o desconectados no están autorizados.

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 (en mayúscula A) no se considera que tenga el mismo rol que admin (en minúscula a).

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 políticas es inusual, pero está permitido por 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. 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.

[Authorize] Atributo

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 los componentes @page a los que se accede a través del enrutador 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 Router, el framework muestra automáticamente el siguiente mensaje de respaldo:

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 a RouteData.PageType 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; }
}

Personaliza el contenido no autorizado con el componente Router

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 funciones del 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 maneja completamente a través de la canalización de middleware de ASP.NET Core y los componentes Razor no se procesan en absoluto en caso de solicitudes no autorizadas o erróneas. 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 por defecto:

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 cumplen con la directiva "content-editor".

Una aplicación Blazor de 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, envuelva <CascadingAuthenticationState> en cualquier parte del árbol de la interfaz de usuario, por ejemplo, alrededor del 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