Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
La memorizzazione nella cache dei token migliora le prestazioni, l'affidabilità e l'esperienza utente dell'applicazione. Microsoft. Identity.Web offre strategie di memorizzazione nella cache flessibili che bilanciano le prestazioni, la persistenza e l'affidabilità operativa.
Informazioni generali
Questa sezione descrive i token Microsoft. Identity.Web caches e perché la memorizzazione nella cache è importante per l'applicazione.
Quali token vengono memorizzati nella cache?
Microsoft. Identity.Web memorizza nella cache diversi tipi di token:
| Tipo di token | Dimensione | Ambito | Sfratto |
|---|---|---|---|
| Token di accesso | ~2 KB | Per (utente/app, tenant, risorsa) | Automatico (basato sulla durata) |
| Token di aggiornamento | Variable | Per account utente | Manuale o basato su criteri |
| Token ID | ~2-7 KB | Per utente | Automatico |
Dove si applica la memorizzazione nella cache dei token:
- App Web che chiamano LE API - Token utente per l'accesso delegato
- API Web che chiamano API a valle - Token OBO (richiede criteri di rimozione accurati)
- Applicazioni daemon - Token per chiamate tra servizi
Perché memorizzare nella cache i token?
Vantaggi delle prestazioni:
- Riduce i round trip per Microsoft Entra ID
- Chiamate API più veloci (L1: <10ms vs L2: ~30ms vs rete: >100ms)
- Bassa latenza per gli utenti finali
Vantaggi dell'affidabilità:
- Continua a funzionare durante le interruzioni temporanee di Microsoft Entra
- Resiliente ai temporanei di rete
- Degradazione graduale quando la cache distribuita fallisce
Vantaggi dei costi:
- Riduce le richieste di autenticazione (limitazione della frequenza)
- Costi di Azure inferiori per le operazioni di autenticazione
Quickstart
Iniziare rapidamente con una delle configurazioni della cache seguenti, a seconda dell'ambiente in uso.
Sviluppo - cache in memoria
L'esempio seguente aggiunge una cache dei token in memoria, adatta per lo sviluppo e gli esempi:
using Microsoft.Identity.Web;
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
Vantaggi:
- Impostazione semplice
- Prestazioni veloci
- Nessuna dipendenza esterna
Svantaggi:
- Cache persa al riavvio dell'app. In un'app Web gli utenti rimangono connessi tramite il cookie, ma devono eseguire di nuovo l'accesso per ottenere un token di accesso e ripopolare la cache
- Non adatto per le distribuzioni multiserver di produzione
- Non condiviso tra istanze dell'applicazione
Produzione - Cache distribuita
Per le applicazioni di produzione, in particolare le distribuzioni multiserver, usare una cache distribuita supportata da Redis o da un altro provider:
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_";
});
Vantaggi:
- Sopravvive ai riavvii dell'app
- Condiviso tra tutte le istanze dell'applicazione
- Memorizzazione automatica nella cache L1+L2
Svantaggi:
- Richiede l'infrastruttura della cache esterna
- Complessità aggiuntiva della configurazione
- Latenza di rete per le operazioni della cache
Scelta di una strategia di cache
Usare il diagramma di flusso decisionale e la matrice seguenti per selezionare la strategia di cache più adatta alla distribuzione.
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
Matrice decisionale
La tabella seguente riepiloga i tipi di cache consigliati per scenari di distribuzione comuni.
| Scenario | Cache consigliata | Motivazione |
|---|---|---|
| Sviluppo locale | In-Memory | Semplicità, nessuna infrastruttura necessaria |
| Esempi/dimostrazioni | In-Memory | Configurazione semplice per le dimostrazioni |
| Produzione a server singolo (riavvii possibili) | In-Memory | Accettabile se le sessioni possono essere ristabilite |
| Produzione multiserver | Redis | Cache condivisa, prestazioni elevate, affidabile |
| applicazioni ospitate su Azure | cache di Azure per Redis | Integrazione Azure nativa, servizio gestito |
| Organizzazione locale | SQL Server | Sfrutta l'infrastruttura esistente |
| Ambienti PostgreSQL | PostgreSQL | Usa il database PostgreSQL esistente, semantica SQL familiare |
| Ambienti a sicurezza elevata | SQL Server e crittografia | Residenza dei dati, crittografia in stato di inattività |
| Test di scenari distribuiti | Memoria distribuita | Verifica il comportamento della cache L2 senza infrastruttura |
Implementazioni della cache
Microsoft. Identity.Web supporta diverse implementazioni della cache. Scegliere quello che corrisponde ai requisiti di infrastruttura e disponibilità.
Cache di memoria
Quando usare:
- Sviluppo e test
- Distribuzioni a server singolo con un comportamento di riavvio accettabile
- Esempi e prototipi
Configuration:
Il codice seguente registra la cache dei token in memoria con le impostazioni predefinite:
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
Con opzioni personalizzate:
È possibile personalizzare i limiti di scadenza e dimensioni passando le opzioni seguenti:
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
});
→ Altre informazioni sulla configurazione della cache in memoria
Cache distribuita (L2) con supporto L1 automatico
Quando usare:
- Distribuzioni multiserver di produzione
- Applicazioni che richiedono la persistenza della cache tra riavvii
- Scenari di disponibilità elevata
Caratteristica chiave: Da Microsoft.Identity.Web v1.8.0, la cache distribuita include automaticamente una cache L1 in memoria per prestazioni e affidabilità.
Redis cache (scelta consigliata)
Aggiungere il stringa di connessione Redis a appsettings.json:
{
"ConnectionStrings": {
"Redis": "localhost:6379"
}
}
Registrare quindi la cache dei token distribuiti e il provider Redis in 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 di Azure per Redis
Per usare cache di Azure per Redis, registrare la cache con il Azure stringa di connessione:
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("AzureRedis");
options.InstanceName = "MyApp_";
});
Formato della stringa di connessione:
<cache-name>.redis.cache.windows.net:6380,password=<access-key>,ssl=True,abortConnect=False
cache di SQL Server
L'esempio seguente configura SQL Server come back-end della cache distribuita:
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);
});
cache Azure Cosmos DB
L'esempio seguente configura Azure Cosmos DB come back-end della cache distribuita:
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;
});
Cache PostgreSQL
Richiede il pacchetto 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
}
}
Registrare quindi la cache PostgreSQL in 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);
});
→ Altre informazioni sulla configurazione della cache distribuita
Cache delle sessioni (non consigliata)
Attenzione
La memorizzazione nella cache basata su sessione presenta limitazioni significative. Usare invece una cache distribuita.
L'esempio seguente illustra la memorizzazione nella cache dei token basata su sessione per riferimento:
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:
- Problemi di dimensioni dei cookie - Token ID di grandi dimensioni con molte attestazioni causano problemi
- conflitti di ambito Scope - non è possibile utilizzare con singleton
TokenAcquisition(ad esempio, Microsoft Graph SDK) - Affinità di sessione richiesta : non funziona correttamente negli scenari con carico bilanciato
- Non consigliato : usare invece la cache distribuita
Configurazione avanzata
Queste opzioni consentono di ottimizzare il comportamento della cache per i criteri di prestazioni, sicurezza e rimozione.
Controllo cache L1
La cache L1 (in memoria) migliora le prestazioni quando si usano cache distribuite. Il codice seguente configura le dimensioni e il comportamento della 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 disabilitare L1:
- Nessuna affinità di sessione nel servizio di bilanciamento del carico
- Gli utenti hanno spesso richiesto l'autenticazione a più fattori a causa dell'incoerenza della cache
- Compromesso prestazionale: l'accesso a L2 è più lento (~30 ms contro ~10 ms)
Criteri di rimozione della cache
I criteri di rimozione controllano quando vengono rimossi i token memorizzati nella cache. Il codice seguente imposta la scadenza assoluta e scorrevole:
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);
});
È anche possibile configurare la rimozione tramite appsettings.json:
{
"TokenCacheOptions": {
"AbsoluteExpirationRelativeToNow": "72:00:00",
"SlidingExpiration": "02:00:00"
}
}
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(
builder.Configuration.GetSection("TokenCacheOptions"));
Raccomandazioni:
- Impostare la scadenza più lunga della durata del token (in genere i token scadono in 1 ora)
- Impostazione predefinita: scadenza variabile di 90 minuti
- Bilanciare l'utilizzo della memoria e l'esperienza utente
- Si consideri: 72 ore assolute + 2 ore scorrevoli per un'esperienza utente valida
→ Altre informazioni sulle strategie di rimozione della cache
Crittografia di dati inattivi
Per proteggere i dati dei token sensibili nelle cache distribuite, abilitare la crittografia tramite ASP.NET Core protezione dei dati.
Computer singolo
In un singolo computer abilitare la crittografia con il provider di protezione dati predefinito:
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.Encrypt = true; // Uses ASP.NET Core Data Protection
});
Sistemi distribuiti (più server)
Importante
I sistemi distribuiti non condividono le chiavi di crittografia per impostazione predefinita. È necessario configurare la condivisione delle chiavi:
Azure Key Vault (scelta consigliata):
Il codice seguente rende persistenti le chiavi per Archiviazione BLOB di Azure e le protegge 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());
Basato su certificati:
Il codice seguente rende persistenti le chiavi di una condivisione file e le protegge con un certificato 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"]));
→ Altre informazioni sulla crittografia e la protezione dei dati
Considerazioni sulle prestazioni della cache
Usare le stime seguenti per pianificare la capacità della cache per l'applicazione.
Stime delle dimensioni dei token
| Tipo di token | Dimensioni tipiche | Per | Note |
|---|---|---|---|
| Token dell'app | ~2 KB | Risorsa × tenant | Rimosso automaticamente |
| Token utente | ~7 KB | Utente × Tenant × Risorsa | Rimozione manuale necessaria |
| Token di aggiornamento | Variable | User | Di lunga durata |
Pianificazione della memoria
Per 500 utenti simultanei che chiamano 3 API:
- Token utente: 500 × 3 × 7 KB = 10,5 MB
- Con sovraccarico: ~15-20 MB
Per 10.000 utenti simultanei:
- Token utente: 10.000 × 3 × 7 KB = 210 MB
- Con sovraccarico: ~300-350 MB
Raccomandazione: Impostare il limite di dimensioni della cache L1 in base agli utenti simultanei previsti.
Procedure consigliate
Seguire queste linee guida per garantire la memorizzazione nella cache dei token affidabile ed efficiente.
Usare la cache distribuita nell'ambiente di produzione - Essenziale per le distribuzioni multiserver
Impostare i limiti di dimensioni della cache appropriati - Impedire l'aumento non limitato della memoria
Configurare i criteri di rimozione - Bilanciare l'esperienza utente e l'utilizzo della memoria
Abilitare la crittografia per i dati sensibili - Proteggere i token a riposo
Monitorare l'integrità della cache - Tenere traccia delle percentuali di riscontri, degli errori e delle prestazioni
Gestire gli errori della cache L2 normalmente : la cache L1 garantisce la resilienza
Comportamento della cache di test - Verificare gli scenari di riavvio e il failover
Non usare la cache di memoria distribuita nell'ambiente di produzione : non persistente o distribuita
Non usare la cache delle sessioni : presenta limitazioni significative
Non impostare la scadenza più breve della durata del token - Forza l'autenticazione non necessaria
Non dimenticare la condivisione delle chiavi di crittografia - I sistemi distribuiti necessitano di chiavi condivise