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.
Questo articolo illustra come diagnosticare e risolvere i problemi comuni relativi alla memorizzazione nella cache dei token in Microsoft. Identity.Web. I problemi relativi alla cache dei token possono manifestarsi come errori di autenticazione, prestazioni ridotte o richieste utente impreviste. Usare i sintomi descritti in ogni sezione per identificare il problema, quindi seguire i passaggi consigliati per risolverlo.
Per una panoramica del funzionamento della memorizzazione nella cache dei token in Microsoft. Identity.Web, vedere panoramica della cache Token.
Prerequisiti
Prima di risolvere i problemi, verificare quanto segue:
- Si sta usando una versione supportata di Microsoft. Identity.Web.
- L'applicazione ha la memorizzazione nella cache dei token configurata in
Program.csoStartup.cs. - È possibile accedere ai log dell'applicazione e, se applicabile, all'infrastruttura della cache distribuita.
Abilitare la registrazione e la diagnostica della cache dei token
L'abilitazione della registrazione dettagliata è il primo passaggio per diagnosticare qualsiasi problema di cache dei token. Microsoft. Identity.Web usa l'infrastruttura di registrazione ASP.NET Core standard e genera eventi tramite il Libreria di Autenticazione Microsoft (MSAL).
Abilitare la registrazione MSAL
Aggiungere la registrazione diagnostica MSAL alla configurazione dell'applicazione:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Identity.Web": "Debug",
"Microsoft.IdentityModel": "Debug"
}
}
}
Sottoscrivere eventi della cache MSAL
Per ottenere visibilità su riscontri nella cache, mancati riscontri ed eventi di serializzazione, sottoscrivere gli eventi di notifica della cache dei token MSAL:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.OnL2CacheFailure = (ex) =>
{
logger.LogWarning(ex, "L2 cache failure encountered.");
// Return true to allow the operation to continue despite the cache failure.
// Return false to propagate the exception.
return true;
};
});
Monitorare le metriche della cache
Per il monitoraggio della produzione, tenere traccia delle metriche chiave seguenti:
- Frequenza di riscontri nella cache : una frequenza di riscontri bassa indica che i token non vengono recuperati dalla cache.
- Latenza cache L2 : la latenza elevata suggerisce un problema di connettività o prestazioni della cache distribuita.
- Errori di serializzazione della cache : errori durante la lettura o la scrittura indicano errori di danneggiamento o mancata corrispondenza della versione.
- Consumo di memoria — una crescita sostenuta può indicare politiche di espulsione mancanti.
Errori di connessione della cache distribuita (L2)
Sintomo
I log dell'applicazione mostrano errori di timeout della connessione o errori di autenticazione intermittenti. Gli utenti riscontrano ritardi durante l'accesso e vengono visualizzate eccezioni come:
Microsoft.Extensions.Caching.StackExchangeRedis.RedisCache:
StackExchange.Redis.RedisConnectionException:
No connection is active/available to service this operation.
Oppure per la cache distribuita di SQL Server:
Microsoft.Data.SqlClient.SqlException:
A network-related or instance-specific error occurred while
establishing a connection to SQL Server.
Motivo
L'archivio di backup della cache distribuita (Redis o SQL Server) non è raggiungibile. I più comuni sono:
- Stringa di connessione errata o credenziali di accesso scadute.
- Regole del firewall di rete che bloccano la connessione dall'host dell'app.
- Il servizio cache è inattivo o in fase di manutenzione.
- Mancata corrispondenza della configurazione SSL/TLS tra il client e il server della cache.
Procedura di diagnostica
- Verificare la connettività. Dall'host dell'applicazione testare la connessione a Redis o SQL Server usando uno strumento di rete, ad esempio
Test-NetConnection(PowerShell) oredis-cli. - Controllare la stringa di connessione. Verificare che il stringa di connessione nella configurazione corrisponda al nome host, alla porta e alle credenziali del server della cache.
- Esaminare le regole del firewall. In Azure verificare che il servizio app o la rete virtuale abbia accesso alla risorsa cache.
- Verificare lo stato del servizio. Nel portale di Azure esaminare l'integrità e le metriche del cache di Azure per Redis o dell'istanza del database SQL.
Soluzione
P 1: Correggere il stringa di connessione
Verificare il stringa di connessione nella configurazione dell'applicazione:
{
"ConnectionStrings": {
"Redis": "your-redis-instance.redis.cache.windows.net:6380,password=your-access-key,ssl=True,abortConnect=False"
}
}
Importante
Impostare abortConnect=False nella stringa di connessione di Redis. Questa impostazione consente all'applicazione di riconnettersi automaticamente dopo gli errori di connessione temporanei anziché riportare immediatamente un errore.
Passaggio 2: Configurare i tentativi e la resilienza
Configurare il callback in modo che l'applicazione OnL2CacheFailure si degradi normalmente quando la cache distribuita non è temporaneamente disponibile:
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.OnL2CacheFailure = (ex) =>
{
// Log the failure for monitoring and alerting.
logger.LogWarning(ex, "Distributed token cache is unavailable. " +
"Falling back to in-memory cache.");
return true; // Continue without the L2 cache.
};
// Set a timeout to avoid blocking the request pipeline.
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
});
Passaggio 3: Aprire le regole del firewall
Se l'applicazione viene eseguita in Servizio app di Azure e la cache si trova in una rete virtuale, aggiungere gli indirizzi IP in uscita del servizio app all'elenco di indirizzi consentiti del firewall della cache.
Errori di deserializzazione della cache
Sintomo
Dopo l'aggiornamento Microsoft. Identity.Web o MSAL.NET, l'applicazione genera eccezioni di deserializzazione durante la lettura dalla cache distribuita. Gli utenti sono costretti a eseguire di nuovo l'accesso e vengono visualizzate eccezioni come:
System.Text.Json.JsonException:
The JSON value could not be converted to the expected type.
O:
Microsoft.Identity.Client.MsalClientException:
Error code: json_parse_failed
Motivo
Il formato di serializzazione della cache dei token è cambiato tra le versioni della libreria. I token memorizzati nella cache dalla versione precedente non possono essere deserializzati dalla nuova versione. Questa situazione si verifica più frequentemente durante gli aggiornamenti delle versioni principali di MSAL.NET o Microsoft. Identity.Web.
Soluzione
Opzione A: Cancellare la cache
La risoluzione più semplice consiste nel cancellare tutte le voci nella cache distribuita. Agli utenti verrà richiesto di ripetere l'autenticazione una sola volta e i token successivi vengono scritti nel nuovo formato.
Per Redis:
redis-cli FLUSHDB
Per SQL Server cache distribuita:
DELETE FROM [dbo].[TokenCache];
Annotazioni
La cancellazione della cache comporta la riautenticazione di tutti gli utenti attivi. Pianificare questa operazione durante una finestra di manutenzione se l'applicazione serve una base utente di grandi dimensioni.
Opzione B: Gestire gli errori di deserializzazione normalmente
Configurare l'adattatore cache per gestire gli errori di deserializzazione come mancati riscontri nella cache anziché errori irreversibili:
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.OnL2CacheFailure = (ex) =>
{
if (ex is JsonException or MsalClientException)
{
logger.LogWarning(ex, "Cache deserialization failed. " +
"Treating as cache miss.");
return true;
}
return false; // Propagate unexpected errors.
};
});
Con questo approccio, le voci della cache interessate vengono sostituite automaticamente quando gli utenti riautenticano e non è necessario scaricare manualmente la cache.
Incongruenza della chiave di crittografia tra server
Sintomo
Gli errori di deserializzazione si verificano nelle distribuzioni multiserver o a istanze multipla, anche se la cache distribuita stessa funziona. I token memorizzati nella cache da un'istanza del server non possono essere letti da un'altra. Nei registri vengono visualizzati errori json_parse_failed o IDW10802.
Motivo
Quando si abilita la crittografia della cache (options.Encrypt = true), Microsoft. Identity.Web usa ASP.NET Core Protezione dati per crittografare le voci della cache. Per configurazione predefinita, ogni istanza del server genera le proprie chiavi di protezione dei dati, il che significa che un'istanza non può decrittografare i dati scritti da un'altra.
Soluzione
Configurare ASP.NET Core Protezione dati per condividere le chiavi di crittografia in tutte le istanze del server.
Opzione A: Archiviazione BLOB di Azure + Azure Key Vault (scelta consigliata per le distribuzioni Azure)
using Microsoft.AspNetCore.DataProtection;
using Azure.Identity;
builder.Services.AddDataProtection()
.PersistKeysToAzureBlobStorage(
new Uri("https://yourstorageaccount.blob.core.windows.net/dataprotection/keys.xml"),
new DefaultAzureCredential())
.ProtectKeysWithAzureKeyVault(
new Uri("https://yourkeyvault.vault.azure.net/keys/dataprotection-key"),
new DefaultAzureCredential());
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.Encrypt = true;
});
Questo approccio archivia l'anello di chiave di protezione dati in Archiviazione BLOB di Azure e protegge le chiavi inattive con una chiave Azure Key Vault. Tutte le istanze dell'applicazione che accedono allo stesso blob e alla stessa chiave possono crittografare e decrittografare le voci della cache.
Opzione B: File system condiviso con protezione del certificato
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\keys"))
.ProtectKeysWithCertificate(certificate);
Suggerimento
Quando si ruota il certificato di protezione dati, usare UnprotectKeysWithAnyCertificate per includere sia i certificati correnti che quelli precedenti. Ciò consente la decrittografia delle chiavi protette con il certificato precedente durante la finestra di rotazione.
Aumento della memoria con cache in memoria
Sintomo
Il consumo di memoria dell'applicazione aumenta costantemente nel tempo. Se l'applicazione viene eseguita in un contenitore o in un piano di servizio app con un limite di memoria fisso, potrebbe riavviarsi o lanciare OutOfMemoryException. Il monitoraggio mostra l'heap gestito in crescita senza essere recuperato da Garbage Collection.
Motivo
Quando si usa AddInMemoryTokenCaches() senza configurare limiti di dimensioni, la cache aumenta senza limiti. Questa situazione è particolarmente problematica nelle applicazioni che servono molti utenti, perché la registrazione del token di ogni utente consuma memoria indefinitamente.
Per impostazione predefinita, MemoryCache non applica una dimensione massima e non rimuove le voci a meno che non sia impostato un criterio di scadenza.
Soluzione
Opzione A: Impostare un limite di dimensioni e una scadenza scorrevole
Configurare la cache in memoria con limiti di dimensioni e criteri di scadenza:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
services.Configure<MsalMemoryTokenCacheOptions>(options =>
{
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
options.SlidingExpiration = TimeSpan.FromHours(2);
});
Con queste impostazioni, le voci della cache scadono dopo 12 ore anche se sono accessibili e le voci a cui non è stato eseguito l'accesso in 2 ore vengono rimosse in precedenza.
Opzione B: Passare a una cache distribuita
Per le applicazioni che servono molti utenti simultanei, una cache in memoria non è scalabile. Passare a una cache distribuita, ad esempio Redis:
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration.GetConnectionString("Redis");
});
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
Una cache distribuita esegue l'offload del consumo di memoria dal processo dell'applicazione, salva in modo permanente i token tra i riavvii dell'applicazione e supporta le distribuzioni a più istanze.
Opzione C: Usare l'architettura ibrida L1/L2
Microsoft. Identity.Web supporta un approccio ibrido che combina una cache L1 veloce in memoria con una cache L2 distribuita persistente:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.L1CacheOptions = new MsalMemoryTokenCacheOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
SlidingExpiration = TimeSpan.FromMinutes(2)
};
});
Con il caching L1/L2, i token a cui si accede di frequente vengono serviti in-memory (L1) con latenza sub-millisecondica, mentre la cache L2 fornisce persistenza e coerenza tra le istanze. La cache L1 usa scadenze brevi per limitare la crescita della memoria.
Richieste di autenticazione a più fattori o di consenso ripetute
Sintomo
Agli utenti viene richiesta ripetutamente l'autenticazione a più fattori (MFA) o il consenso anche se hanno completato di recente questi passaggi. L'applicazione non sembra trovare i token esistenti nella cache.
Motivo
Questo problema si verifica quando il tentativo di ricerca nella cache dei token non riesce a trovare una voce memorizzata corrispondente all'account utente corrente. I più comuni sono:
- La chiave della cache è diversa da quella usata quando il token è stato originariamente archiviato. Ciò può verificarsi se cambia il
HomeAccountIdo il contesto del tenant. - L'applicazione esegue più istanze dietro un servizio di bilanciamento del carico con memorizzazione nella cache in memoria e la richiesta dell'utente viene instradata a un'istanza che non ha il token.
- Le attestazioni o l'ambito richiesto dall'applicazione sono state modificate, quindi il token memorizzato nella cache non soddisfa il nuovo requisito.
- L'affinità di sessione non è abilitata, causando il routing dell'utente a un'istanza diversa che non dispone del token memorizzato nella cache.
Procedura di diagnostica
- Controllare il tipo di cache. Se si usa
AddInMemoryTokenCaches()in una distribuzione a più istanze, i token memorizzati nella cache in un'istanza non sono disponibili in un'altra. Passare a una cache distribuita. - Verificare l'identificatore dell'account. Abilitare la registrazione a livello di debug e cercare i messaggi contenenti
HomeAccountId. Verificare che l'identificatore sia coerente tra le richieste. - Esaminare gli ambiti. Verificare che gli ambiti richiesti da
GetAccessTokenForUserAsynccorrispondano agli ambiti a cui è stato originariamente concesso il consenso. Una mancata corrispondenza dell'ambito fa sì che MSAL richieda un nuovo token. - Esaminare i criteri di accesso condizionale. I criteri di accesso condizionale che richiedono l'autenticazione dettagliata per risorse specifiche causano richieste aggiuntive che non sono correlate alla memorizzazione nella cache.
Soluzione
Passaggio 1: Passare alla memorizzazione nella cache distribuita
Se l'applicazione esegue più istanze, usare una cache distribuita per condividere i token tra istanze:
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration.GetConnectionString("Redis");
});
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
Passaggio 2: Verificare ambiti coerenti
Verificare che gli ambiti richiesti durante l'acquisizione dei token corrispondano a quanto configurato durante l'autenticazione:
// In authentication setup — initial scopes.
.EnableTokenAcquisitionToCallDownstreamApi(new[] { "User.Read", "Mail.Read" })
// When acquiring a token — use the same scopes.
var token = await tokenAcquisition.GetAccessTokenForUserAsync(
new[] { "User.Read", "Mail.Read" });
Passaggio 3: Abilitare l'affinità di sessione (soluzione temporanea)
Se non è possibile passare immediatamente a una cache distribuita, abilitare l'affinità di sessione (sessioni permanenti) nel servizio di bilanciamento del carico in modo che le richieste di un utente vengano sempre instradate alla stessa istanza. Questo approccio è una soluzione alternativa temporanea e presenta limitazioni di scalabilità.
Problemi di prestazioni della cache
Sintomo
Il recupero dei token è lento e le chiamate API downstream aumentano la latenza. Il monitoraggio mostra tempi di risposta medi elevati per le richieste che acquisiscono token. La latenza non è causata dal provider di identità, perché i token vengono serviti dalla cache.
Motivo
I problemi di prestazioni della cache in genere derivano da:
- Latenza cache L2 elevata. La cache distribuita è sottoposta a carico elevato, geograficamente distante dall'applicazione o tramite un livello di servizio sottodimensionato.
- Voci della cache dei token di grandi dimensioni. Le applicazioni che memorizzano nella cache i token per molte risorse per utente possono produrre voci di cache serializzate di grandi dimensioni lente da leggere e scrivere.
- Nessuna cache L1. Ogni acquisizione di token passa alla cache distribuita in rete, anche per i token usati di frequente.
Soluzione
Passaggio 1: Abilitare la cache in memoria L1
La cache L1 archivia i token a cui si accede di frequente nella memoria del processo, evitando round trip di rete alla cache L2:
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.L1CacheOptions = new MsalMemoryTokenCacheOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
SlidingExpiration = TimeSpan.FromMinutes(2)
};
});
Con questa configurazione, i token serviti da L1 hanno una latenza di sub millisecondi, mentre i token che non sono in L1 fallback alla cache distribuita L2.
Passaggio 2: Ottimizzare il livello cache distribuita
Se la latenza della cache L2 è elevata, prendere in considerazione le azioni seguenti:
- Aumentare la capacità dell'istanza di Redis. Passare a un livello superiore (ad esempio, da Basic a Standard o Premium in cache di Azure per Redis) per ottenere una maggiore velocità effettiva e una latenza inferiore.
- Abilita replica geografica. Se l'applicazione serve gli utenti in più aree, usare cache di Azure per Redis replica geografica in modo che la cache sia vicina al calcolo di ogni area.
- Esaminare la configurazione di rete. Usare collegamento privato o integrazione rete virtuale per ridurre gli hop di rete tra l'applicazione e la cache.
Passaggio 3: Ridurre le dimensioni dei token serializzati
Se le voci della cache dei token sono di grandi dimensioni, verificare se l'applicazione richiede token per risorse in eccesso. Ogni combinazione univoca di risorsa e ambito contribuisce alla dimensione dell'entrata della cache. Consolidare le chiamate API, laddove possibile, per ridurre il numero di token di accesso distinti memorizzati nella cache per utente.
Rimozione della cache Redis
Sintomo
Agli utenti viene richiesto di eseguire di nuovo l'autenticazione intermittente e non esiste alcun modello in base alla scadenza del token. Il monitoraggio di Redis mostra evicted_keys un aumento e la used_memory metrica è vicina al maxmemory limite.
Motivo
Quando Redis raggiunge il limite configurato maxmemory, rimuove le chiavi in base alla politica configurata maxmemory-policy. Il criterio predefinito (volatile-lru) rimuove le chiavi usate meno di recente con una scadenza impostata. Se l'istanza di Redis viene condivisa con altri dati dell'applicazione, le voci della cache dei token competono per lo spazio e possono essere rimosse prima della scadenza naturale.
Soluzione
Passaggio 1: Controllare il criterio di rimozione
Verificare i criteri di rimozione correnti:
redis-cli CONFIG GET maxmemory-policy
Per le cache dei token, volatile-lru (impostazione predefinita) è in genere appropriata perché le voci della cache dei token hanno delle scadenze impostate. Tuttavia, se altri dati senza scadenza consumano memoria, gli elementi del token vengono rimossi per primi.
Passaggio 2: Usare un'istanza di Redis dedicata
Isolare la cache dei token da altri dati dell'applicazione usando un'istanza redis separata:
{
"ConnectionStrings": {
"RedisTokenCache": "token-cache-redis.redis.cache.windows.net:6380,password=...,ssl=True,abortConnect=False",
"RedisAppData": "app-data-redis.redis.cache.windows.net:6380,password=...,ssl=True,abortConnect=False"
}
}
// Register the token cache Redis instance specifically for distributed caching.
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration.GetConnectionString("RedisTokenCache");
});
Passaggio 3: Aumentare il limite di memoria Redis
Se un'istanza dedicata non è fattibile, aumentare l'impostazione nell'istanza maxmemory esistente. In cache di Azure per Redis aumentare le prestazioni fino a un livello superiore o aumentare le dimensioni della cache.
Passaggio 4: Impostare le scadenze appropriate per le voci della cache
Assicurarsi che le voci della cache dei token abbiano scadenze ragionevoli in modo che le voci non aggiornate vengano rimosse prima che venga raggiunto il limite di memoria:
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
options.SlidingExpiration = TimeSpan.FromHours(2);
});
Crescita della tabella della cache distribuita SQL
Sintomo
La tabella della cache distribuita di SQL aumenta continuamente, aumentando lo spazio su disco. Le query di database sulla tabella della cache diventano più lente nel tempo. È possibile che vengano visualizzati avvisi relativi al monitoraggio delle dimensioni delle tabelle o dei limiti di archiviazione.
Motivo
La cache distribuita SQL Server (Microsoft.Extensions.Caching.SqlServer) non rimuove automaticamente le voci scadute. Le voci scadute rimangono nella tabella fino a quando non vengono eliminate in modo esplicito. Nel corso del tempo, la tabella aumenta senza limiti e riduce le prestazioni delle query e consuma l'archiviazione.
Soluzione
Passaggio 1: Configurare un processo di pulizia ricorrente
Creare un processo SQL Server Agent o un'attività pianificata che rimuove periodicamente le voci scadute:
-- Delete expired entries from the SQL distributed cache table.
-- Schedule this query to run every 30 minutes.
DELETE FROM [dbo].[TokenCache]
WHERE ExpiresAtTime < GETUTCDATE();
Suggerimento
In database SQL di Azure, in cui SQL Server Agent non è disponibile, utilizzare Automazione di Azure, Funzioni di Azure con un trigger timer o Elastic Jobs per pianificare la pulizia.
Passaggio 2: Aggiungere un indice per una pulizia efficiente
Se la tabella della cache non dispone già di un indice nella colonna di scadenza, aggiungerne una per velocizzare l'operazione di eliminazione:
CREATE NONCLUSTERED INDEX IX_TokenCache_ExpiresAtTime
ON [dbo].[TokenCache] (ExpiresAtTime);
Passaggio 3: Monitorare le dimensioni della tabella
Aggiungere il monitoraggio per tenere traccia del numero di righe e delle dimensioni della tabella nel tempo:
SELECT
COUNT(*) AS TotalEntries,
COUNT(CASE WHEN ExpiresAtTime < GETUTCDATE() THEN 1 END) AS ExpiredEntries,
COUNT(CASE WHEN ExpiresAtTime >= GETUTCDATE() THEN 1 END) AS ActiveEntries
FROM [dbo].[TokenCache];
Passaggio 4: Prendere in considerazione il passaggio a Redis
Se la gestione della pulizia della cache SQL è eccessivamente complessa, passare a Redis, che gestisce automaticamente la scadenza tramite il meccanismo TTL predefinito:
// Replace SQL distributed cache with Redis.
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration.GetConnectionString("Redis");
});
Suggerimenti generali sulla risoluzione dei problemi
Usare questi suggerimenti quando il problema riscontrato non corrisponde a uno degli scenari specifici di questo articolo.
Verificare che la cache sia in uso
Aggiungere la registrazione temporanea per verificare che i token vengano letti e scritti nella cache:
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.Encrypt = false; // Disable encryption temporarily for debugging only.
options.OnL2CacheFailure = (ex) =>
{
logger.LogError(ex, "L2 cache operation failed.");
return true;
};
});
Verificare la presenza di più registrazioni della cache
Se nel codice di avvio sono presenti più chiamate a AddInMemoryTokenCaches() o AddDistributedTokenCaches(), l'ultima registrazione vince. Verificare che sia registrato un solo tipo di cache.
Esaminare la durata del token
Tenere presente che i token di accesso hanno una durata limitata (in genere da 60 a 90 minuti). Se gli utenti segnalano la necessità di ripetere l'autenticazione dopo questo periodo, il comportamento potrebbe essere previsto anziché un problema di cache. I token di aggiornamento vengono usati per ottenere i nuovi token di accesso in modo invisibile all'utente e vengono archiviati nella cache. Se il token di aggiornamento è mancante o scaduto, l'utente deve ripetere l'autenticazione.
Eseguire il test con una cache pulita
Durante la diagnosi dei problemi, iniziare cancellando la cache per escludere voci danneggiate o non aggiornate:
- Cache in memoria: Riavviare l'applicazione.
-
Redis: Eseguire
FLUSHDBnel database della cache. - SQL Server: Elimina tutte le righe dalla tabella della cache.
Cache dei token vuota dopo il riavvio dell'applicazione
Sintomo
Gli utenti sono costretti a ripetere l'autenticazione dopo ogni riavvio o ridistribuzione dell'applicazione. La cache distribuita appare vuota o i token non vengono salvati in modo permanente.
Motivo
Questo problema si verifica in genere quando si usa una cache in memoria (AddInMemoryTokenCaches()) o la cache di memoria distribuita non persistente (AddDistributedMemoryCache()) nell'ambiente di produzione. Nessuna di queste opzioni rende persistenti i token tra i riavvii dell'applicazione.
Il AddDistributedMemoryCache() metodo registra un'implementazione IDistributedCache che archivia i dati in memoria. Nonostante il nome "distribuito", non rende persistenti i dati esternamente ed è destinato solo allo sviluppo e ai test.
Soluzione
Passare a un'implementazione persistente della cache distribuita:
// Register a persistent cache (Redis example).
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("Redis");
options.InstanceName = "MyApp_";
});
// Use distributed token caches instead of in-memory.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
Avvertimento
Non confondere AddDistributedMemoryCache() con una cache distribuita persistente. Usare AddStackExchangeRedisCache() (Redis), AddDistributedSqlServerCache() (SQL Server) o un'altra implementazione persistente IDistributedCache per i carichi di lavoro di produzione.