Vyřešte problémy s mezipamětí tokenů v Microsoft. Identity.Web

Tento článek vám pomůže diagnostikovat a vyřešit problémy s mezipamětí tokenů v Microsoft. Identity.Web. Problémy s mezipamětí tokenů můžou způsobit selhání ověřování, snížený výkon nebo neočekávané výzvy k přihlášení. Přehled toho, jak funguje ukládání tokenů do mezipaměti v Microsoft Identity.Web, viz Přehled mezipamětiToken.

Předpoklady

Než začnete řešit potíže, potvrďte následující:

  • Používáte podporovanou verzi Microsoft. Identity.Web
  • Vaše aplikace má nakonfigurované ukládání tokenů do mezipaměti v Program.cs nebo Startup.cs.
  • Máte přístup k protokolům aplikace a v případě potřeby máte infrastrukturu distribuované mezipaměti.

Povolení protokolování a diagnostiky mezipaměti tokenů

Povolte podrobné protokolování jako první diagnostický krok. Microsoft. Identity.Web používá infrastrukturu protokolování ASP.NET Core a generuje události prostřednictvím Identity a ověřování Microsoftu (MSAL).

Povolte protokolování MSAL

Nastavte úroveň protokolu pro Debug knihovny identit ve vaší appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.Identity.Web": "Debug",
      "Microsoft.IdentityModel": "Debug"
    }
  }
}

Přihlášení k odběru událostí mezipaměti MSAL

Přihlaste se k odběru událostí oznámení mezipaměti tokenů MSAL, abyste mohli sledovat přístupy do mezipaměti, neúspěšné přístupy a činnost serializace:

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

Monitorování metrik mezipaměti

V případě provozního monitorování sledujte tyto klíčové metriky:

  • Míra úspěchu při načítání z mezipaměti – nízká míra úspěchu indikuje, že tokeny nejsou načítány z mezipaměti.
  • Latence mezipaměti L2 – vysoká latence naznačuje problém s připojením nebo výkonem distribuované mezipaměti.
  • Chyby serializace mezipaměti – chyby při čtení nebo zápisu signalizují poškození nebo nesoulad verzí.
  • Spotřeba paměti – trvalý růst může indikovat chybějící zásady vyřazení.

Selhání připojení distribuované mezipaměti (L2)

Symptom

Protokoly aplikací zobrazují chyby vypršení časového limitu připojení nebo přerušované chyby ověřování. Uživatelé mají zpoždění při přihlašování a zobrazují se výjimky, jako jsou:

Microsoft.Extensions.Caching.StackExchangeRedis.RedisCache:
  StackExchange.Redis.RedisConnectionException: 
  No connection is active/available to service this operation.

Nebo pro SQL Server distribuovanou mezipaměť:

Microsoft.Data.SqlClient.SqlException:
  A network-related or instance-specific error occurred while 
  establishing a connection to SQL Server.

Příčina

Záložní úložiště distribuované mezipaměti (Redis nebo SQL Server) je nedostupné. Mezi obvyklé příčiny patří:

  • Nesprávný připojovací řetězec nebo vypršely přístupové údaje.
  • Pravidla firewallu sítě blokují připojení z hostitele aplikace.
  • Služba mezipaměti je nefunkční nebo prochází údržbou.
  • Neshoda konfigurace PROTOKOLU SSL/TLS mezi klientem a serverem mezipaměti

Diagnostické kroky

K identifikaci selhání připojení postupujte takto:

  1. Ověřte připojení. Z hostitele aplikace otestujte připojení k Redis nebo SQL Server pomocí Test-NetConnection (PowerShell) nebo redis-cli.
  2. Zkontrolujte připojovací řetězec. Ověřte, že připojovací řetězec odpovídá názvu hostitele, portu a přihlašovacím údajům serveru mezipaměti.
  3. Zkontrolujte pravidla brány firewall. V Azure ověřte, že služba App Service nebo virtuální síť má přístup k prostředku mezipaměti.
  4. Kontrola stavu funkčnosti. Na portálu Azure zkontrolujte stav a metriky vaší instance Azure Cache for Redis nebo služby SQL Database.

Řešení

Krok 1: Oprava připojovacího řetězce

Ověřte připojovací řetězec v appsettings.json:

{
  "ConnectionStrings": {
    "Redis": "your-redis-instance.redis.cache.windows.net:6380,password=your-access-key,ssl=True,abortConnect=False"
  }
}

Důležité

Nastavte abortConnect=False v řetězci připojení Redis. Toto nastavení umožňuje aplikaci, aby se po přechodných selháních připojení automaticky znovu připojila a nevyvolá se okamžitě.

Krok 2: Konfigurace opakování a odolnosti

Nakonfigurujte OnL2CacheFailure zpětné volání tak, aby vaše aplikace degraduje elegantně, když je distribuovaná mezipaměť dočasně nedostupná.

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

Krok 3: Otevření pravidel brány firewall

Pokud aplikace běží v Azure App Service a mezipaměť je ve virtuální síti, přidejte odchozí IP adresy služby App Service do seznamu povolených bránou firewall mezipaměti.

Chyby deserializace mezipaměti

Symptom

Po upgradu Microsoft.Identity.Web nebo MSAL.NET dojde k vyvolání výjimek při deserializaci při čtení z distribuované mezipaměti. Uživatelé se musí znovu přihlásit a zobrazí se výjimky, například:

System.Text.Json.JsonException:
  The JSON value could not be converted to the expected type.

Nebo:

Microsoft.Identity.Client.MsalClientException:
  Error code: json_parse_failed

Příčina

Formát serializace mezipaměti tokenů se změnil mezi verzemi knihovny. Tokeny uložené v mezipaměti předchozí verze nelze deserializovat novou verzí. K tomuto problému dochází nejčastěji při upgradu hlavní verze MSAL.NET nebo Microsoft.Identity.Web.

Řešení

Možnost A: Vymazání mezipaměti

Nejjednodušším řešením je vymazat všechny položky v distribuované mezipaměti. Uživatelé se znovu prověří jednou a další tokeny se zapíšou v novém formátu.

Vyprázdnění mezipaměti Redis:

redis-cli FLUSHDB

Nebo vymažte tabulku SQL Server distribuované mezipaměti:

DELETE FROM [dbo].[TokenCache];

Poznámka:

Vymazání mezipaměti způsobí opětovné ověření všech aktivních uživatelů. Naplánujte tuto operaci během časového období údržby, pokud vaše aplikace obsluhuje velkou uživatelskou základnu.

Možnost B: Elegantní zpracování chyb deserializace

Nakonfigurujte adaptér mezipaměti tak, aby selhání deserializace byla považována za neúspěchy mezipaměti místo fatálních chyb.

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.
    };
});

Při tomto přístupu se ovlivněné položky mezipaměti automaticky nahradí při opětovném ověření uživatelů a nevyžaduje se žádné ruční vyprázdnění mezipaměti.

Neshoda šifrovacích klíčů mezi servery

Symptom

V nasazeních s více instancemi dochází k chybám deserializace, i když distribuovaná mezipaměť funguje. Tokeny uložené v mezipaměti jedné instance serveru nemůžou číst jiné. V protokolech se zobrazí chyby jako json_parse_failed nebo IDW10802.

Příčina

Pokud je povolené šifrování mezipaměti (options.Encrypt = true), Microsoft. Identity.Web používá k šifrování položek mezipaměti ASP.NET Core Data Protection. Ve výchozím nastavení každá instance serveru generuje vlastní klíče ochrany dat, takže jedna instance nemůže dešifrovat záznamy zapsané jiným serverem.

Řešení

Nakonfigurujte ASP.NET Core Ochrana dat tak, aby sdílela šifrovací klíče napříč všemi instancemi serveru.

Option A: Azure Blob Storage + Azure Key Vault (doporučeno pro nasazení 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;
});

Tato konfigurace ukládá okruh klíčů ochrany dat do Azure Blob Storage a chrání neaktivní uložené klíče pomocí Azure Key Vault. Všechny instance aplikace, které přistupují ke stejnému blobu a klíči, mohou šifrovat a dešifrovat položky mezipaměti navzájem.

Možnost B: Sdílený systém souborů s ochranou certifikátů

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\keys"))
    .ProtectKeysWithCertificate(certificate);

Návod

Při obměně certifikátu Ochrany dat použijte UnprotectKeysWithAnyCertificate k zahrnutí aktuálních i předchozích certifikátů. To umožňuje dešifrování klíčů chráněných starým certifikátem během okna rotace.

Růst paměti při použití cache v paměti RAM

Symptom

Spotřeba paměti aplikace se v průběhu času stále zvyšuje. Pokud aplikace běží v kontejneru nebo plánu služby App Service s pevným limitem paměti, nakonec se restartuje nebo vyvolá OutOfMemoryException. Monitorování ukazuje růst spravované haldy bez zásahu garbage collectoru.

Příčina

Použití AddInMemoryTokenCaches() bez omezení velikosti způsobí nevázaných nárůst mezipaměti. Tato situace je obzvláště problematická v aplikacích, které obsluhují mnoho uživatelů, protože položka tokenu každého uživatele spotřebovává paměť neomezeně dlouho.

Ve výchozím nastavení MemoryCache nevynucuje maximální velikost a neodstraňuje položky, pokud není nastavená zásada vypršení platnosti.

Řešení

Možnost A: Nastavení limitu velikosti a posuvného vypršení platnosti

Nakonfigurujte mezipaměť v paměti pomocí zásad vypršení platnosti:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddInMemoryTokenCaches();

services.Configure<MsalMemoryTokenCacheOptions>(options =>
{
    options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
    options.SlidingExpiration = TimeSpan.FromHours(2);
});

U těchto nastavení vyprší platnost položek po 12 hodinách bez ohledu na přístup a položky nečinné po dobu 2 hodin se vyřadí dříve.

Možnost B: Přepnutí do distribuované mezipaměti

U aplikací s mnoha souběžnými uživateli se mezipaměť v paměti nes škáluje. Přepněte do distribuované mezipaměti, jako je Redis:

services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = Configuration.GetConnectionString("Redis");
});

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDistributedTokenCaches();

Distribuovaná mezipaměť snižuje zatížení paměti z procesu aplikace, zachovává tokeny napříč restartováními a podporuje nasazení s více instancemi.

Možnost C: Použití hybridní architektury L1/L2

Microsoft. Identity.Web podporuje hybridní přístup, který kombinuje rychlou mezipaměť L1 v paměti s trvalou distribuovanou mezipamětí L2. Konfigurace hybridní mezipaměti L1/L2:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDistributedTokenCaches();

services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
    options.L1CacheOptions = new MsalMemoryTokenCacheOptions
    {
        AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
        SlidingExpiration = TimeSpan.FromMinutes(2)
    };
});

Při použití mezipaměti L1/L2 se často přistupované tokeny obsluhují přímo z paměti L1 s latencí pod jednu milisekundu. Mezipaměť L2 poskytuje trvalost a konzistenci mezi instancemi. Mezipaměť L1 využívá krátké vypršení platnosti k omezení růstu paměti.

Symptom

Uživatelům se opakovaně zobrazuje výzva k vícefaktorovým ověřováním (MFA) nebo k vyjádření souhlasu, i když tyto kroky provedli nedávno. Aplikace nemůže najít existující tokeny v mezipaměti.

Příčina

K tomuto problému dochází, když vyhledávání v mezipaměti tokenů neodpovídá uložené položce pro aktuální uživatelský účet. Mezi obvyklé příčiny patří:

  • Klíč mezipaměti se liší od klíče použitého při uložení tokenu. K této situaci může dojít v případě, že se kontext tenanta HomeAccountId změní.
  • Aplikace spouští několik instancí za vyrovnávačem zatížení s ukládáním do mezipaměti v paměti a požadavky jsou směrovány do instance, která nemá uživatelský token.
  • Požadované nároky nebo obory se změnily, takže token v mezipaměti nesplňuje nový požadavek.
  • Spřažení relací není povolené, takže uživatelé jsou směrováni do různých instancí, které nemají tokeny uložené v mezipaměti.

Diagnostické kroky

Pokud chcete zjistit, proč se tokeny v mezipaměti nenašly, postupujte takto:

  1. Zkontrolujte typ mezipaměti. Pokud používáte AddInMemoryTokenCaches() při nasazení s více instancemi, tokeny uložené v mezipaměti v jedné instanci nejsou v jiné instanci k dispozici. Přepněte do distribuované mezipaměti.
  2. Ověřte identifikátor účtu. Povolte protokolování na úrovni ladění a vyhledejte HomeAccountId. Ověřte, že je identifikátor konzistentní napříč požadavky.
  3. Zkontrolujte rozsahy. Ověřte, že rozsahy požadované pomocí GetAccessTokenForUserAsync odpovídají rozsahům původně odsouhlaseným. Nesoulad oborů způsobí, že MSAL požádá o nový token.
  4. Zkontrolujte zásady podmíněného přístupu. Zásady podmíněného přístupu Microsoft Entra ID, které vyžadují zesílené ověření specifických zdrojů, způsobují nečekané výzvy, které nesouvisejí s ukládáním do mezipaměti.

Řešení

Krok 1: Přepnutí do distribuované mezipaměti

Pokud vaše aplikace spouští více instancí, použijte distribuovanou mezipaměť ke sdílení tokenů napříč instancemi:

services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = Configuration.GetConnectionString("Redis");
});

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDistributedTokenCaches();

Krok 2: Ověření konzistentních oborů

Ujistěte se, že obory, které požadujete při získávání tokenů, odpovídají oborům nakonfigurovaným během ověřování:

// 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" });

Krok 3: Povolení spřažení relací (dočasné alternativní řešení)

Pokud nemůžete hned přepnout na distribuovanou mezipaměť, povolte v nástroji pro vyrovnávání zatížení spřažení relací (rychlé relace). Přesměrování podle relace směruje požadavky uživatele do stejné instance. Tento přístup představuje dočasné alternativní řešení s omezeními škálovatelnosti.

Problémy s výkonem mezipaměti

Symptom

Načítání tokenů je pomalé a podřízená volání rozhraní API mají zvýšenou latenci. Monitorování ukazuje vysokou průměrnou dobu odezvy pro žádosti o získání tokenu. Latence není způsobena zprostředkovatelem identity – tokeny jsou poskytovány z mezipaměti.

Příčina

Problémy s výkonem mezipaměti obvykle vyplývají z:

  • Vysoká latence mezipaměti L2 Distribuovaná mezipaměť je pod velkým zatížením, geograficky vzdálená od aplikace nebo používá podsazenou úroveň služby.
  • Velké položky mezipaměti tokenů. Aplikace, které ukládají tokeny do mezipaměti pro mnoho prostředků na uživatele, mohou vytvářet velké serializované položky do mezipaměti, které jsou pomalé při čtení a zápisu.
  • Žádná L1 cache. Každé pořízení tokenu přejde do distribuované mezipaměti přes síť, a to i pro tokeny, které se používají často.

Řešení

Krok 1: Povolení mezipaměti L1 v paměti

Mezipaměť L1 ukládá často používané tokeny v paměti procesu, čímž se vyhne síťovým přenosům do mezipaměti L2.

services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
    options.L1CacheOptions = new MsalMemoryTokenCacheOptions
    {
        AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
        SlidingExpiration = TimeSpan.FromMinutes(2)
    };
});

V této konfiguraci mají tokeny obsluhované z L1 podmilisekundovou latenci. Tokeny, které nejsou v L1, se vrátí do distribuované mezipaměti L2.

Krok 2: Optimalizace úrovně distribuované mezipaměti

Pokud je latence mezipaměti L2 vysoká, zvažte následující akce:

  • Navyšte kapacitu instance Redisu. Přejděte na vyšší úroveň (například z úrovně Basic na Standard nebo Premium v Azure Cache for Redis), abyste získali větší propustnost a nižší latenci.
  • Povolte geografickou replikaci. Pokud vaše aplikace obsluhuje uživatele ve více oblastech, použijte geografickou replikaci Azure Cache for Redis, aby byla mezipaměť blíže výpočetním zdrojům jednotlivých oblastí.
  • Zkontrolujte konfiguraci sítě. Pomocí Private Link nebo integrace s virtuální sítí VNet snižte počet skoků v síti mezi aplikací a mezipamětí.

Krok 3: Zmenšení serializované velikosti tokenu

Pokud jsou položky mezipaměti tokenů velké, zkontrolujte, jestli aplikace požaduje tokeny pro více prostředků, než je potřeba. Každá jedinečná kombinace prostředků a rozsahů přispívá k velikosti položky v mezipaměti. Konsolidujte volání rozhraní API, pokud je to možné, aby se snížil počet jedinečných přístupových tokenů uložených v mezipaměti pro jednotlivé uživatele.

Vyřazení mezipaměti Redis

Symptom

Uživatelům se přerušovaně zobrazí výzva k opětovnému ověření bez vzoru na základě vypršení platnosti tokenu. Monitorování Redis ukazuje evicted_keys zvýšení a used_memory přiblížení k limitu maxmemory.

Příčina

Když Redis dosáhne svého maxmemory limitu, vyřazuje klíče podle nastaveného maxmemory-policy. Výchozí zásada (volatile-lru) vyřadí nejméně naposledy použité klíče, které mají vypršení platnosti. Pokud je instance Redis sdílena s jinými daty aplikace, položky mezipaměti tokenů soupeří o prostor a je možné je předčasně vyřadit.

Řešení

Krok 1: Kontrola zásad vyřazení

Zkontrolujte aktuální zásady vyřazení:

redis-cli CONFIG GET maxmemory-policy

U mezipamětí tokenů (výchozí nastavení) je vhodné, volatile-lru protože položky mezipaměti tokenů mají vypršení platnosti. Pokud však jiná data bez vypršení platnosti spotřebovávají paměť, položky tokenů se nejprve vyřadí.

Krok 2: Použití vyhrazené instance Redis

Izolujte mezipaměť tokenů od jiných dat aplikace pomocí vyhrazené instance Redis:

{
  "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");
});

Krok 3: Zvýšení limitu paměti Redis

Pokud není možné zřídit vyhrazenou instanci, zvyšte maxmemory nastavení. V Azure Cache for Redis vertikálně navyšte kapacitu na vyšší úroveň nebo zvětšete velikost mezipaměti.

Krok 4: Nastavení vypršení platnosti příslušných položek mezipaměti

Nastavte přiměřené vypršení platnosti, aby se před vyčerpáním paměti odebraly zastaralé položky:

services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
    options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
    options.SlidingExpiration = TimeSpan.FromHours(2);
});

Růst tabulek distribuované mezipaměti SQL

Symptom

Tabulka distribuované mezipaměti SQL neustále roste a spotřebovává místo na disku. Databázové dotazy na tabulku mezipaměti jsou pomalé v průběhu času a můžou se zobrazit upozornění týkající se velikosti tabulky nebo omezení úložiště.

Příčina

Distribuovaná mezipaměť SQL Server (Microsoft.Extensions.Caching.SqlServer) automaticky neodebere položky, jejichž platnost vypršela. Položky s vypršenou platností zůstanou, dokud se explicitně nevyprázdní, což způsobí nárůst nevázaných tabulek, snížení výkonu dotazů a spotřebu úložiště.

Řešení

Krok 1: Nastavení opakované úlohy čištění

Vytvořte SQL Server Agent úlohu nebo naplánovanou úlohu, která bude pravidelně odebírat položky, jejichž platnost vypršela:

-- Delete expired entries from the SQL distributed cache table.
-- Schedule this query to run every 30 minutes.
DELETE FROM [dbo].[TokenCache]
WHERE ExpiresAtTime < GETUTCDATE();

Návod

V Azure SQL Database, kde SQL Server Agent není k dispozici, použijte Azure Automation, Azure Functions s časovým spouštěčem nebo Elastic Jobs k naplánování vyčištění.

Krok 2: Přidání indexu pro efektivní vyčištění

Pokud tabulka mezipaměti ještě nemá ve sloupci vypršení platnosti index, přidejte jednu pro urychlení operace odstranění:

CREATE NONCLUSTERED INDEX IX_TokenCache_ExpiresAtTime
ON [dbo].[TokenCache] (ExpiresAtTime);

Krok 3: Monitorování velikosti tabulky

Přidejte monitorování pro sledování počtu řádků a velikosti tabulky v průběhu času:

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];

Krok 4: Zvažte přepnutí na Redis

Pokud je správa čištění mezipaměti SQL náročná, přepněte na Redis, který automaticky zpracovává vypršení platnosti prostřednictvím integrovaného mechanismu TTL:

// Replace SQL distributed cache with Redis.
services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = Configuration.GetConnectionString("Redis");
});

Obecné tipy pro řešení potíží

Tyto tipy použijte v případě, že váš problém neodpovídá konkrétnímu scénáři v tomto článku.

Ověřte, že se mezipaměť používá.

Přidejte dočasné protokolování pro potvrzení, že tokeny se čtou a zapisují do mezipaměti:

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

Kontrola více registrací mezipaměti

Pokud ve spouštěcím kódu existuje více volání AddInMemoryTokenCaches() nebo AddDistributedTokenCaches(), převáží poslední registrace. Ověřte, že je zaregistrovaný pouze jeden typ mezipaměti.

Kontrola doby života tokenu

Přístupové tokeny mají omezenou životnost (obvykle 60–90 minut). Pokud uživatelé po tomto období hlásí, že se znovu autentizovali, je to očekávané chování, nikoliv problém s mezipamětí. Obnovovací tokeny získávají nové přístupové tokeny bezobslužně a ukládají se do mezipaměti. Pokud token aktualizace chybí nebo vypršela jeho platnost, musí se uživatel znovu autorizovat.

Testování s čistou mezipamětí

Při diagnostice problémů vymažte mezipaměť, aby se vyloučily poškozené nebo zastaralé položky:

  • Mezipaměť v paměti: Restartujte aplikaci.
  • Redis: Spusťte FLUSHDB na databázi mezipaměti.
  • SQL Server: Odstraňte všechny řádky z tabulky mezipaměti.

Mezipaměť tokenů je po restartování aplikace prázdná.

Symptom

Uživatelé musí po každém restartování nebo opětovném nasazení aplikace znovu provést ověření. Distribuovaná mezipaměť se zobrazuje jako prázdná nebo tokeny se neuchovávají.

Příčina

K tomuto problému obvykle dochází v případě, že v produkčním prostředí používáte mezipaměť v paměti (AddInMemoryTokenCaches()) nebo neuskutečnou distribuovanou paměťovou mezipaměť (AddDistributedMemoryCache()). Žádná možnost neuchová tokeny napříč restartováními aplikace.

AddDistributedMemoryCache() zaregistruje IDistributedCache implementaci, která ukládá data do paměti. I přes "distribuovaný" název neuchovává data externě a je určen pouze pro vývoj a testování.

Řešení

Přepnutí na trvalou distribuovanou mezipaměť:

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

Výstraha

Nezaměňujte AddDistributedMemoryCache() s trvalou distribuovanou mezipamětí. Pro produkční úlohy použijte AddStackExchangeRedisCache() (Redis), AddDistributedSqlServerCache() (SQL Server) nebo jinou trvalou implementaci IDistributedCache.