Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
El almacenamiento en caché de tokens mejora el rendimiento, la confiabilidad y la experiencia del usuario de las aplicaciones. Microsoft. Identity.Web proporciona estrategias de almacenamiento en caché flexibles que equilibran el rendimiento, la persistencia y la confiabilidad operativa.
Visión general
En esta sección se describen los tokens que Microsoft.Identity.Web almacena en caché y por qué el almacenamiento en caché es importante para tu aplicación.
¿Qué tokens se almacenan en caché?
Microsoft. Identity.Web almacena en caché varios tipos de tokens:
| Tipo de token | Tamaño | Ámbito | Expulsión |
|---|---|---|---|
| Tokens de acceso | ~2 KB | Por (usuario/aplicación, entidad, recurso) | Automático (basado en la vida útil) |
| Tokens de renovación | Variable | Por cuenta de usuario | Basado en directivas o manuales |
| Tokens de identificador | ~2-7 KB | Por usuario | Automático |
Donde se aplica el almacenamiento en caché de tokens:
- API de llamadas de aplicaciones web : tokens de usuario para el acceso delegado
- API web que llaman a las API de bajada : tokens de OBO (requiere directivas de expulsión cuidadosas)
- Aplicaciones de daemón - tokens de aplicación exclusiva para llamadas de servicio a servicio
¿Por qué los tokens de caché?
Ventajas de rendimiento:
- Reduce los viajes de ida y vuelta a Microsoft Entra ID
- Llamadas API más rápidas (L1: <10 ms frente a L2: ~30 ms frente a red: >100 ms)
- Menor latencia para los usuarios finales
Ventajas de confiabilidad:
- Continúa trabajando durante interrupciones temporales de Microsoft Entra
- Resistente a los transitorios de red
- Degradación gradual cuando falla la caché distribuida
Ventajas de costos:
- Reduce las solicitudes de autenticación (prevención de la limitación de frecuencia)
- Menores costos de Azure para las operaciones de autenticación
Inicio rápido
Empiece a trabajar rápidamente con una de las siguientes configuraciones de caché, en función de su entorno.
Desarrollo: caché en memoria
En el ejemplo siguiente se agrega una caché de tokens en memoria, adecuada para el desarrollo y los ejemplos:
using Microsoft.Identity.Web;
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
Ventajas:
- Instalación simple
- Rendimiento rápido
- Sin dependencias externas
Desventajas:
- Caché perdida en el reinicio de la aplicación. En una aplicación web, los usuarios permanecen conectados a través de la cookie, pero deben volver a iniciar sesión para obtener un token de acceso y volver a rellenar la memoria caché.
- No es adecuado para implementaciones de varios servidores de producción
- No se comparte entre instancias de aplicación
Producción: caché distribuida
En el caso de las aplicaciones de producción, especialmente las implementaciones de varios servidores, use una caché distribuida respaldada por Redis u otro proveedor:
using Microsoft.Identity.Web;
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
// Choose your cache implementation
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("Redis");
options.InstanceName = "MyApp_";
});
Ventajas:
- Sobrevive a los reinicios de la aplicación
- Compartido en todas las instancias de aplicación
- Almacenamiento en caché automático L1+L2
Desventajas:
- Requiere infraestructura de caché externa
- Complejidad adicional de la configuración
- Latencia de red para las operaciones de caché
Elección de una estrategia de caché
Use el siguiente diagrama de flujo de decisión y matriz para seleccionar la estrategia de caché que mejor se adapte a la implementación.
flowchart TD
Start([Token Caching<br/>Decision]) --> Q1{Production<br/>Environment?}
Q1 -->|No - Dev/Test| DevChoice[In-Memory Cache<br/>AddInMemoryTokenCaches]
Q1 -->|Yes| Q2{Multiple Server<br/>Instances?}
Q2 -->|No - Single Server| Q3{App Restarts<br/>Acceptable?}
Q3 -->|Yes| DevChoice
Q3 -->|No| DistChoice
Q2 -->|Yes| DistChoice[Distributed Cache<br/>AddDistributedTokenCaches]
DistChoice --> Q4{Cache<br/>Implementation?}
Q4 -->|High Performance| Redis[Redis Cache<br/>StackExchange.Redis<br/>⭐ Recommended]
Q4 -->|Azure Native| Azure[Azure Cache for Redis,<br/>Azure Cosmos DB,<br/>or Azure Database for PostgreSQL]
Q4 -->|On-Premises| SQL[SQL Server Cache<br/>AddDistributedSqlServerCache]
Q4 -->|Testing| DistMem[Distributed Memory<br/>Not for production]
Redis --> L1L2[Automatic L1+L2<br/>Caching]
Azure --> L1L2
SQL --> L1L2
DistMem --> L1L2
L1L2 --> Config[Configure Options<br/>MsalDistributedTokenCacheAdapterOptions]
DevChoice --> MemConfig[Configure Memory Options<br/>MsalMemoryTokenCacheOptions]
style Start fill:#e1f5ff
style DevChoice fill:#d4edda
style DistChoice fill:#fff3cd
style Redis fill:#d1ecf1
style L1L2 fill:#f8d7da
Matriz de decisión
En la tabla siguiente se resumen los tipos de caché recomendados para escenarios de implementación comunes.
| Escenario | Caché recomendada | Justificación |
|---|---|---|
| Desarrollo local | In-Memory | Simplicidad, sin necesidad de infraestructura |
| Ejemplos y demostraciones | In-Memory | Configuración sencilla para demostraciones |
| Producción de un solo servidor (reinicia Ok) | In-Memory | Aceptable si se pueden restablecer las sesiones |
| Producción en servidores múltiples | Redis | Caché compartida, alto rendimiento, confiable |
| Aplicaciones hospedadas en Azure | Azure Cache for Redis | Integración de Azure nativa, servicio administrado |
| Empresa local | SQL Server | Aprovecha la infraestructura existente |
| Entornos de PostgreSQL | PostgreSQL | Usa una base de datos PostgreSQL existente, semántica de SQL conocida. |
| Entornos de alta seguridad | SQL Server + Cifrado | Residencia de los datos, cifrado en reposo |
| Probar escenarios distribuidos | Memoria distribuida | Prueba el comportamiento de la caché L2 sin infraestructura |
Implementaciones de caché
Microsoft. Identity.Web admite varias implementaciones de caché. Elija la que coincida con los requisitos de infraestructura y disponibilidad.
Caché en memoria
Cuándo usar:
- Desarrollo y pruebas
- Implementaciones de servidor único con un comportamiento de reinicio aceptable
- Ejemplos y prototipos
Configuration:
El código siguiente registra la caché de tokens en memoria con la configuración predeterminada:
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
Con opciones personalizadas:
Puede personalizar los límites de expiración y tamaño pasando las opciones:
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches(options =>
{
// Token cache entry will expire after this duration
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);
// Limit cache size (default is unlimited)
options.SizeLimit = 500 * 1024 * 1024; // 500 MB
});
→ Más información sobre la configuración de caché en memoria
Caché distribuida (L2) con compatibilidad automática con L1
Cuándo usar:
- Implementaciones de varios servidores de producción
- Aplicaciones que requieren persistencia de caché entre reinicios
- Escenarios de alta disponibilidad
Característica clave: Desde Microsoft.Identity.Web v1.8.0, la caché distribuida incluye automáticamente una caché de nivel 1 en memoria para mejorar el rendimiento y la confiabilidad.
Redis Cache (recomendado)
Agregue la cadena de conexión de Redis a appsettings.json:
{
"ConnectionStrings": {
"Redis": "localhost:6379"
}
}
A continuación, registre la caché de tokens distribuida y el proveedor de Redis en Program.cs:
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.TokenCacheProviders.Distributed;
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
// Redis cache implementation
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("Redis");
options.InstanceName = "MyApp_"; // Unique prefix per application
});
// Optional: Configure distributed cache behavior
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
// Control L1 cache size
options.L1CacheOptions.SizeLimit = 500 * 1024 * 1024; // 500 MB
// Handle L2 cache failures gracefully
options.OnL2CacheFailure = (exception) =>
{
if (exception is StackExchange.Redis.RedisConnectionException)
{
// Log the failure
// Optionally attempt reconnection
return true; // Retry the operation
}
return false; // Don't retry
};
});
Azure Cache for Redis
Para usar Azure Cache for Redis, registre su memoria caché con su cadena de conexión de Azure.
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("AzureRedis");
options.InstanceName = "MyApp_";
});
Formato de la cadena de conexión:
<cache-name>.redis.cache.windows.net:6380,password=<access-key>,ssl=True,abortConnect=False
caché de SQL Server
En el ejemplo siguiente se configura SQL Server como back-end de caché distribuida:
builder.Services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString("TokenCacheDb");
options.SchemaName = "dbo";
options.TableName = "TokenCache";
// Set expiration longer than access token lifetime (default 1 hour)
// This prevents cache entries from expiring before tokens
options.DefaultSlidingExpiration = TimeSpan.FromMinutes(90);
});
caché de Azure Cosmos DB
En el ejemplo siguiente se configura Azure Cosmos DB como back-end de caché distribuida:
builder.Services.AddCosmosCache((CosmosCacheOptions options) =>
{
options.ContainerName = builder.Configuration["CosmosCache:ContainerName"];
options.DatabaseName = builder.Configuration["CosmosCache:DatabaseName"];
options.ClientBuilder = new CosmosClientBuilder(
builder.Configuration["CosmosCache:ConnectionString"]);
options.CreateIfNotExists = true;
});
Caché de PostgreSQL
Requiere el paquete NuGet Microsoft.Extensions.Caching.Postgres.
appsettings.json:
{
"ConnectionStrings": {
"PostgresCache": "Host=localhost;Database=mydb;Username=myuser;Password=mypassword"
},
"PostgresCache": {
"SchemaName": "public",
"TableName": "token_cache",
"CreateIfNotExists": true
}
}
A continuación, registre la memoria caché de PostgreSQL en Program.cs:
builder.Services.AddDistributedPostgresCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString("PostgresCache");
options.SchemaName = builder.Configuration["PostgresCache:SchemaName"];
options.TableName = builder.Configuration["PostgresCache:TableName"];
options.CreateIfNotExists = builder.Configuration.GetValue<bool>("PostgresCache:CreateIfNotExists");
options.DefaultSlidingExpiration = TimeSpan.FromMinutes(90);
});
→ Más información sobre la configuración de caché distribuida
Caché de sesión (no recomendada)
Precaución
El almacenamiento en caché basado en sesión tiene limitaciones significativas. Use una caché distribuida en su lugar.
En el ejemplo siguiente se muestra el almacenamiento en caché de tokens basado en sesión como referencia:
using Microsoft.Identity.Web.TokenCacheProviders.Session;
// In Program.cs
builder.Services.AddSession();
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddSessionTokenCaches();
// In middleware pipeline
app.UseSession(); // Must be before UseAuthentication()
app.UseAuthentication();
app.UseAuthorization();
Limitaciones:
- Problemas de tamaño de cookies - Los tokens de ID grandes con muchas reclamaciones provocan problemas
- Conflictos de Scope: no se puede usar con singleton
TokenAcquisition(por ejemplo, SDK de Microsoft Graph) - Afinidad de sesión necesaria : no funciona bien en escenarios de carga equilibrada
- No recomendado : use la caché distribuida en su lugar.
Configuración avanzada
Estas opciones permiten ajustar el comportamiento de la caché para las directivas de rendimiento, seguridad y expulsión.
Control de caché L1
La caché L1 (en memoria) mejora el rendimiento cuando se usan cachés distribuidas. El código siguiente configura el tamaño y el comportamiento de la caché L1:
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
// Control L1 cache size (default: 500 MB)
options.L1CacheOptions.SizeLimit = 100 * 1024 * 1024; // 100 MB
// Disable L1 cache if session affinity is not available
// (forces all requests to use L2 cache for consistency)
options.DisableL1Cache = false;
});
Cuándo deshabilitar L1:
- No hay afinidad de sesión en el equilibrador de carga
- A los usuarios se les solicita con frecuencia MFA debido a la incoherencia de caché
- Compensación: el acceso L2 es más lento, de alrededor de 30 ms frente a 10 ms.
Directivas de expulsión de caché
Las directivas de expulsión controlan cuándo se quitan los tokens almacenados en caché. El código siguiente establece la expiración absoluta y deslizante:
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
// Absolute expiration (removed after this time, regardless of use)
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(72);
// Sliding expiration (renewed on each access)
options.SlidingExpiration = TimeSpan.FromHours(2);
});
También puede configurar la expulsión a través de appsettings.json:
{
"TokenCacheOptions": {
"AbsoluteExpirationRelativeToNow": "72:00:00",
"SlidingExpiration": "02:00:00"
}
}
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(
builder.Configuration.GetSection("TokenCacheOptions"));
Recomendaciones:
- Establecer la expiración más larga que la duración del token (los tokens suelen expirar en 1 hora)
- Valor predeterminado: expiración deslizante de 90 minutos
- Equilibrio entre el uso de memoria y la experiencia del usuario
- Considere: 72 horas absolutas + 2 horas flexibles para una buena experiencia de usuario
→ Más información sobre las estrategias de expulsión de caché
Cifrado en reposo
Para proteger los datos confidenciales de los tokens en cachés distribuidos, habilite el cifrado a través de Protección de datos de ASP.NET Core.
Una máquina
En una sola máquina, habilite el cifrado con el proveedor de protección de datos integrado:
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.Encrypt = true; // Uses ASP.NET Core Data Protection
});
Sistemas distribuidos (varios servidores)
Importante
Los sistemas distribuidos no comparten claves de cifrado de forma predeterminada. Debe configurar el uso compartido de claves:
Azure Key Vault (recomendado):
El código siguiente conserva las claves para Azure Blob Storage y las protege con Azure Key Vault:
using Microsoft.AspNetCore.DataProtection;
builder.Services.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri(builder.Configuration["DataProtection:BlobUri"]))
.ProtectKeysWithAzureKeyVault(
new Uri(builder.Configuration["DataProtection:KeyIdentifier"]),
new DefaultAzureCredential());
Basado en certificados:
El código siguiente conserva las claves en un recurso compartido de archivos y las protege con un certificado X.509:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\keys"))
.ProtectKeysWithCertificate(
new X509Certificate2("current.pfx", builder.Configuration["CertPassword"]))
.UnprotectKeysWithAnyCertificate(
new X509Certificate2("current.pfx", builder.Configuration["CertPassword"]),
new X509Certificate2("previous.pfx", builder.Configuration["PrevCertPassword"]));
→ Más información sobre el cifrado y la protección de datos
Consideraciones sobre el rendimiento de la memoria caché
Use las estimaciones siguientes para planear la capacidad de caché de la aplicación.
Estimaciones del tamaño del token
| Tipo de token | Tamaño típico | Por | Notas |
|---|---|---|---|
| Tokens de aplicación | ~2 KB | Inquilino × Recurso | Eliminado automáticamente |
| Tokens de usuario | ~7 KB | Usuario × Inquilino × Recurso | Expulsión manual necesaria |
| Tokens de actualización | Variable | Usuario | Larga duración |
Planeación de memoria
Para 500 usuarios simultáneos que llaman a 3 API:
- Tokens de usuario: 500 × 3 × 7 KB = 10,5 MB
- Con sobrecarga: ~15-20 MB
Para 10 000 usuarios simultáneos:
- Tokens de usuario: 10 000 × 3 × 7 KB = 210 MB
- Con sobrecarga: ~300-350 MB
Recomendación: Establezca el límite de tamaño de caché L1 en función de los usuarios simultáneos esperados.
procedimientos recomendados
Siga estas instrucciones para garantizar el almacenamiento en caché de tokens confiable y eficaz.
Uso de la caché distribuida en producción : esencial para implementaciones de varios servidores
Establecer límites adecuados del tamaño del caché – evitar el crecimiento sin límites de la memoria
Configurar políticas de expulsión - equilibrar el uso de la experiencia de usuario y de la memoria
Habilitación del cifrado para datos confidenciales : protección de tokens en reposo
Supervisión del estado de la caché : seguimiento de las tasas de aciertos, los errores y el rendimiento
Control de errores de caché L2 correctamente : la memoria caché L1 garantiza la resistencia.
Probar el comportamiento de la caché - verificación de escenarios de reinicio y conmutación por error
No usar la caché de memoria distribuida en producción : no persistente ni distribuida
No usar la memoria caché de sesión : tiene limitaciones significativas
No establecer la expiración más corta que la duración del token - fuerza una reautenticación innecesaria.
No olvide el uso compartido de claves de cifrado : los sistemas distribuidos necesitan claves compartidas