Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
A cache de tokens melhora o desempenho das aplicações, a fiabilidade e a experiência do utilizador. Microsoft. O Identity.Web oferece estratégias de cache flexíveis que equilibram desempenho, persistência e fiabilidade operacional.
Descrição geral
Esta secção descreve quais tokens a Microsoft.Identity.Web armazena em cache e explica por que o armazenamento em cache é importante para o seu aplicativo.
Que tokens são armazenados em cache?
Microsoft. O Identity.Web armazena em cache vários tipos de tokens:
| Tipo de token | Tamanho | Scope | Despejo |
|---|---|---|---|
| Tokens de acesso | ~2 KB | Per (utilizador/app, cliente, recurso) | Automático (baseado em vida útil) |
| Tokens de Atualização | Variable | Por conta de utilizador | Manual ou baseado em políticas |
| Fichas de identificação | ~2-7 KB | Por utilizador | Automático |
Onde se aplica a cache de tokens:
- APIs de chamadas de aplicações web - Tokens de utilizador para acesso delegado
- APIs Web que chamam APIs downstream - tokens OBO (requerem políticas de remoção cuidadosas)
- Aplicações daemon - Tokens exclusivos para aplicações para chamadas serviço-a-serviço
Por que armazenar tokens em cache?
Benefícios de Desempenho:
- Reduz as viagens de ida e volta ao Microsoft Entra ID
- Chamadas API mais rápidas (L1: <10ms vs L2: ~30ms vs rede: >100ms)
- Menor latência para utilizadores finais
Benefícios de Fiabilidade:
- Continua a trabalhar durante interrupções temporárias da Microsoft Entra
- Resiliente a perturbações de rede
- Degradação suave quando a cache distribuída falha
Custos-benefícios:
- Reduz os pedidos de autenticação (evitação de limitação)
- Custos mais baixos do Azure para operações de autenticação
Início Rápido
Comece rapidamente com uma das seguintes configurações de cache, dependendo do seu ambiente.
Desenvolvimento - cache em memória
O exemplo seguinte adiciona uma cache de tokens em memória, adequada para desenvolvimento e samples:
using Microsoft.Identity.Web;
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
Vantagens:
- Configuração simples
- Desempenho rápido
- Sem dependências externas
Desvantagens:
- Cache perdida ao reiniciar a aplicação. Numa aplicação web, os utilizadores mantêm-se iniciados através do cookie, mas têm de voltar a iniciar sessão para obter um token de acesso e repovoar a cache
- Não adequado para implementações multi-servidor em produção
- Não partilhado entre instâncias de aplicação
Produção - cache distribuída
Para aplicações de produção, especialmente implementações multi-servidor, utilize uma cache distribuída apoiada pelo Redis ou outro fornecedor:
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_";
});
Vantagens:
- Sobrevive a reinícios da aplicação
- Partilhado entre todas as instâncias de aplicação
- Cache automática L1+L2
Desvantagens:
- Requer infraestrutura de cache externa
- Complexidade adicional de configuração
- Latência de rede para operações de cache
Escolher uma estratégia de cache
Use o seguinte fluxograma de decisão e matriz para selecionar a estratégia de cache que melhor se adequa à sua implementação.
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 decisão
A tabela seguinte resume os tipos de cache recomendados para cenários de implementação comuns.
| Scenario | Cache Recomendado | Fundamentação |
|---|---|---|
| Desenvolvimento local | In-Memory | Simplicidade, sem necessidade de infraestrutura |
| Amostras/demonstrações | In-Memory | Configuração fácil para demonstrações |
| Ambiente de produção em servidor único (reinícios aceitáveis) | In-Memory | Aceitável se as sessões puderem ser restabelecidas |
| Produção multi servidor | Redis | Cache partilhada, alto desempenho, fiável |
| Aplicações hospedadas no Azure | Cache do Azure para Redis | Integração nativa com Azure, serviço gerido |
| Empresa on-premises | SQL Server | Aproveita a infraestrutura existente |
| Ambientes PostgreSQL | PostgreSQL | Utiliza a base de dados PostgreSQL existente, semântica SQL familiar |
| Ambientes de alta segurança | SQL Server + Encriptação | Residência de dados, encriptação em repouso |
| Testar cenários distribuídos | Memória Distribuída | Testa o comportamento da cache L2 sem infraestrutura |
Implementações de cache
Microsoft. O Identity.Web suporta várias implementações de cache. Escolha aquele que corresponda às suas necessidades de infraestrutura e disponibilidade.
Cache na memória
Quando usar:
- Desenvolvimento e testes
- Implementações de servidor único com comportamento aceitável de reinício
- Amostras e protótipos
Configuration:
O seguinte código regista a cache de tokens em memória com as definições predefinidas:
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
Com opções personalizadas:
Pode personalizar limites de validade e tamanho passando opções:
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
});
→ Saiba mais sobre a configuração da cache em memória
Cache distribuída (L2) com suporte automático a L1
Quando usar:
- Implementações em produção de multi-servidores
- Aplicações que requerem persistência de cache durante reinícios
- Cenários de elevada disponibilidade
Característica chave: Desde Microsoft. Identity.Web v1.8.0, a cache distribuída inclui automaticamente uma cache L1 em memória para desempenho e fiabilidade.
Cache Redis (recomendado)
Adicione a cadeia de conexão Redis ao appsettings.json:
{
"ConnectionStrings": {
"Redis": "localhost:6379"
}
}
Depois, regista a cache de tokens distribuídos e o fornecedor Redis em 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
};
});
Cache do Azure para Redis
Para usar Cache do Azure para Redis, registe a cache com a sua cadeia de ligação Azure.
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("AzureRedis");
options.InstanceName = "MyApp_";
});
Formato da cadeia de ligação:
<cache-name>.redis.cache.windows.net:6380,password=<access-key>,ssl=True,abortConnect=False
Cache do SQL Server
O exemplo seguinte configura o SQL Server como backend de cache distribuída:
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);
});
Azure Cosmos DB Cache
O exemplo seguinte configura o Azure Cosmos DB como backend de cache distribuída:
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;
});
PostgreSQL cache
Requer o pacote 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
}
}
Depois regista a cache PostgreSQL em 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);
});
→ Saiba mais sobre configuração de cache distribuída
Cache de sessão (não recomendado)
Atenção
O cache baseado em sessões tem limitações significativas. Usa uma cache distribuída em vez disso.
O exemplo seguinte mostra a cache de tokens baseada em sessões para referência:
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();
Limitations:
- Problemas com o tamanho das cookies - Tokens de identificação grandes com muitas declarações causam problemas
-
Conflitos de Âmbito - Não pode ser usado com um singleton
TokenAcquisition(por exemplo, Microsoft Graph SDK) - Afinidade de sessão necessária - Não funciona bem em cenários com balanceamento de carga
- Não recomendado - Use cache distribuído em vez disso
Configuração avançada
Estas opções permitem-lhe ajustar o comportamento da cache para desempenho, segurança e políticas de despejo.
Controlo de cache L1
A cache L1 (em memória) melhora o desempenho quando utiliza caches distribuídos. O seguinte código configura o tamanho e o comportamento da cache 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;
});
Quando desativar o L1:
- Ausência de afinidade de sessão no balanceador de carga
- Os utilizadores são solicitados frequentemente a usar MFA devido à inconsistência do cache do sistema.
- Compensação: o acesso L2 é mais lento (~30ms em comparação com ~10ms)
Políticas de remoção de cache
As políticas de despejo controlam quando os tokens em cache são removidos. O seguinte código define a expiração absoluta e a 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);
});
Também pode configurar a expulsão via appsettings.json:
{
"TokenCacheOptions": {
"AbsoluteExpirationRelativeToNow": "72:00:00",
"SlidingExpiration": "02:00:00"
}
}
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(
builder.Configuration.GetSection("TokenCacheOptions"));
Recommendations:
- Defina a expiração mais longa do que a vida útil dos tokens (os tokens normalmente expiram em 1 hora)
- Padrão: 90 minutos de expiração deslizante
- Equilíbrio entre o uso de memória e a experiência do utilizador
- Considere: 72 horas absolutas + 2 horas ajustáveis para uma boa experiência do utilizador
→ Saiba mais sobre estratégias de despejo da cache
Encriptação em repouso
Para proteger dados sensíveis de tokens em caches distribuídos, ative a encriptação através do ASP.NET Core Data Protection.
Única máquina
Numa única máquina, ative a encriptação com o fornecedor de Proteção de Dados incorporado:
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.Encrypt = true; // Uses ASP.NET Core Data Protection
});
Sistemas distribuídos (múltiplos servidores)
Importante
Os sistemas distribuídos não partilham chaves de encriptação por defeito. Deve configurar a partilha de chaves:
Azure Key Vault (recomendado):
O código seguinte mantém as chaves do Armazenamento de Blobs do Azure e protege-as com o 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());
Baseado em certificados:
O seguinte código mantém as chaves de uma partilha de ficheiros e protege-as com um 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"]));
→ Saiba mais sobre encriptação e proteção de dados
Considerações de desempenho da cache
Use as seguintes estimativas para planear a capacidade de cache para a sua aplicação.
Estimativas do tamanho do token
| Tipo de token | Tamanho Típico | Per | Notes |
|---|---|---|---|
| Tokens de aplicação | ~2 KB | Recurso × Inquilino | Removido automaticamente |
| Tokens de utilizador | ~7 KB | Utilizador × Tenant × Recurso | É necessário despejo manual |
| Atualizar tokens | Variable | User | Longevidade |
Planeamento da memória
Para 500 utilizadores simultâneos a chamar 3 APIs:
- Tokens de utilizador: 500 × 3 × 7 KB = 10,5 MB
- Com sobrecarga: ~15-20 MB
Para 10.000 utilizadores simultâneos:
- Tokens de utilizador: 10.000 × 3 × 7 KB = 210 MB
- Com custos fixos: ~300-350 MB
Recomendação: Defina o limite do tamanho da cache L1 com base nos utilizadores concorrentes esperados.
Melhores práticas
Siga estas orientações para garantir um cache de tokens fiável e eficiente.
Use cache distribuído em produção - Essencial para as implementações com múltiplos servidores
Defina limites de tamanho de cache apropriados - Evite o crescimento ilimitado da memória
Configurar políticas de despejo - Equilibrar a experiência de utilizador e o uso de memória
Ativar encriptação para dados sensíveis - Proteger os tokens em repouso
Monitorizar a saúde da cache - Acompanhar as taxas de acerto, falhas e desempenho
Trate as falhas do cache L2 com elegância - o cache L1 garante resiliência
Testar o comportamento da cache - Verificar cenários de reinício e failover
Não uses cache de memória distribuída em produção - Não é persistente nem distribuída
Não uses o cache de sessão - Tem limitações significativas
Não defina a expiração mais curta do que a vida útil do token - Força a reautenticação desnecessária
Não se esqueça da partilha de chaves de encriptação - Sistemas distribuídos precisam de chaves partilhadas