Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Эта статья помогает диагностировать и устранять проблемы с кэшем маркеров в Microsoft. Identity.Web. Проблемы с кэшем маркеров могут привести к сбоям проверки подлинности, снижению производительности или непредвиденным запросам на вход. Общие сведения о том, как работает кэширование маркеров в Microsoft. Identity.Web см. в разделе Token cache overview.
Необходимые условия
Прежде чем устранять неполадки, убедитесь в следующем:
- Вы используете поддерживаемую версию Microsoft. Identity.Web.
- В приложении настроено
Program.csкэширование токенов илиStartup.cs. - У вас есть доступ к журналам приложений и, если применимо, инфраструктуре распределенного кэша.
Включите ведение журнала кэша токенов и диагностику
Включите подробное ведение журнала в качестве первого шага диагностики. Microsoft. Identity.Web использует инфраструктуру ведения журнала ASP.NET Core и выдает события через Microsoft Authentication Library (MSAL).
Включение ведения журнала MSAL
Установите уровень журнала Debug для библиотек удостоверений в вашем appsettings.json.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Identity.Web": "Debug",
"Microsoft.IdentityModel": "Debug"
}
}
}
Подписка на события кэша MSAL
Подпишитесь на события уведомления о кэше токенов 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;
};
});
Мониторинг метрик кэша
Для мониторинга рабочей среды отслеживайте следующие ключевые метрики:
- Частота попадания в кэш — низкая частота попаданий указывает, что токены не извлекаются из кэша.
- Задержка кэша L2 — высокая задержка предполагает подключение к распределенном кэшу или проблему с производительностью.
- Ошибки сериализации кэша — ошибки при чтении или записи указывают на повреждение или несоответствие версий.
- Потребление памяти — устойчивый рост может указывать на отсутствие политик вытеснения.
Сбои подключения распределенного кэша (L2)
Симптом
В журналах приложений отображаются ошибки времени ожидания подключения или периодические сбои проверки подлинности. Пользователи испытывают задержки входа и отображаются исключения, такие как:
Microsoft.Extensions.Caching.StackExchangeRedis.RedisCache:
StackExchange.Redis.RedisConnectionException:
No connection is active/available to service this operation.
Или для распределенного кэша SQL Server:
Microsoft.Data.SqlClient.SqlException:
A network-related or instance-specific error occurred while
establishing a connection to SQL Server.
Причина
Хранилище резервной копии распределенного кэша (Redis или SQL Server) недоступно. Наиболее вероятные причины:
- Неверные строка подключения или учетные данные доступа с истекшим сроком действия.
- Правила брандмауэра сети блокируют подключение с узла приложения.
- Служба кэша отключена или находится в состоянии обслуживания.
- Несоответствие конфигурации SSL/TLS между клиентом и сервером кэша.
Этапы диагностики
Выполните следующие действия, чтобы определить сбой подключения:
- Проверьте подключение. На узле приложения проверьте подключение к Redis или SQL Server с помощью
Test-NetConnection(PowerShell) илиredis-cli. - Проверьте строку подключения. Убедитесь, что строка подключения соответствует имени узла, портам и учетным данным сервера кэша.
- Проверьте правила брандмауэра. В Azure убедитесь, что служба приложений или виртуальная сеть может получить доступ к ресурсу кэша.
- Проверьте работоспособность служб. На портале Azure проверьте работоспособность и метрики экземпляра Кэш Azure для Redis или базы данных SQL.
Решение
Шаг 1: Исправьте строку подключения
Проверьте строку подключения в appsettings.json:
{
"ConnectionStrings": {
"Redis": "your-redis-instance.redis.cache.windows.net:6380,password=your-access-key,ssl=True,abortConnect=False"
}
}
Это важно
Установите abortConnect=False в строке подключения Redis. Этот параметр позволяет приложению автоматически восстанавливать подключение после временных сбоев, а не немедленно выбрасывать ошибки.
Шаг 2. Настройка повторных попыток и устойчивости
Настройте обратный OnL2CacheFailure вызов, чтобы приложение корректно справилось, когда распределенный кэш временно недоступен.
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);
});
Шаг 3. Открытие правил брандмауэра
Если приложение выполняется в Служба приложений Azure, а кэш находится в виртуальной сети, добавьте исходящие IP-адреса службы приложений в список разрешений брандмауэра кэша.
Ошибки десериализации кэша
Симптом
После обновления Microsoft. Identity.Web или MSAL.NET приложение создает исключения десериализации при чтении из распределенного кэша. Пользователи должны снова войти в систему, и вы увидите такие исключения, как:
System.Text.Json.JsonException:
The JSON value could not be converted to the expected type.
Или:
Microsoft.Identity.Client.MsalClientException:
Error code: json_parse_failed
Причина
Формат сериализации кэша маркеров изменился между версиями библиотеки. Токены, кэшированные предыдущей версией, не могут быть десериализированы новой версией. Эта проблема возникает чаще всего при обновлении основных версий MSAL.NET или Microsoft. Identity.Web.
Решение
Вариант A. Очистка кэша
Самое простое исправление — очистить все записи в распределенном кэше. Пользователи повторно выполняют проверку подлинности один раз, а последующие маркеры записываются в новом формате.
Очистка кэша Redis:
redis-cli FLUSHDB
Или снимите таблицу распределенного кэша SQL Server:
DELETE FROM [dbo].[TokenCache];
Замечание
Очистка кэша требует от всех активных пользователей повторной аутентификации. Запланируйте эту операцию во время периода обслуживания, если приложение служит большой пользовательской базой.
Вариант B: Корректная обработка ошибок десериализации
Настройте адаптер кэша так, чтобы сбои десериализации рассматривались как пропуски кэша, а не как фатальные ошибки.
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.
};
});
При таком подходе затронутые записи кэша автоматически заменяются при повторной проверке подлинности пользователей, и очистка кэша вручную не требуется.
Несоответствие ключа шифрования между серверами
Симптом
Ошибки десериализации возникают в развертываниях с несколькими экземплярами, даже если распределенный кэш работает. Токены, кэшированные одним экземпляром сервера, не могут быть считаны другим. В журналах отображаются ошибки json_parse_failed или IDW10802.
Причина
Если шифрование кэша включено (options.Encrypt = true), Microsoft. Identity.Web использует ASP.NET Core Data Protection для шифрования записей кэша. По умолчанию каждый экземпляр сервера создает собственные ключи защиты данных, поэтому один экземпляр не может расшифровывать записи, написанные другим.
Решение
Настройте ASP.NET Core Data Protection для совместного использования ключей шифрования во всех экземплярах сервера.
Option A: Хранилище BLOB-объектов Azure + Azure Key Vault (рекомендуется для развертываний 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;
});
Эта конфигурация сохраняет кольцо ключей Data Protection в Хранилище BLOB-объектов Azure и защищает неактивных ключей с помощью Azure Key Vault. Все экземпляры приложений, обращаюющиеся к одному и тому же большому двоичному объекту и ключу, могут шифровать и расшифровывать записи кэша друг друга.
Вариант B. Общая файловая система с защитой сертификатов
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\keys"))
.ProtectKeysWithCertificate(certificate);
Подсказка
При смене сертификата защиты данных используйте UnprotectKeysWithAnyCertificate для включения как текущих, так и предыдущих сертификатов. Это позволяет расшифровать ключи, которые были защищены старым сертификатом, во время периода ротации.
Рост памяти с помощью кэша в памяти
Симптом
Потребление памяти приложения постоянно растет со временем. Если приложение выполняется в контейнере или плане службы приложений с фиксированным ограничением памяти, оно в конечном итоге перезапускается или вызывает исключение OutOfMemoryException. Мониторинг показывает, что управляемая куча растет без восстановления сборкой мусора.
Причина
Использование AddInMemoryTokenCaches() без ограничений размера приводит к росту несвязанного кэша. Эта ситуация особенно проблематична в приложениях, которые обслуживают множество пользователей, так как токен каждого пользователя постоянно расходует память.
По умолчанию MemoryCache не применяет максимальный размер и не вытесняет записи, если не задана политика истечения срока действия.
Решение
Вариант A: Установить ограничения размера и скользящее истечение срока действия
Настройте кэш в памяти с политиками окончания срока действия:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
services.Configure<MsalMemoryTokenCacheOptions>(options =>
{
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
options.SlidingExpiration = TimeSpan.FromHours(2);
});
При использовании этих параметров срок действия записей истекает через 12 часов, независимо от доступа, и записи бездействия в течение 2 часов удаляются ранее.
Вариант B. Переключение в распределенный кэш
Для приложений с множеством одновременных пользователей кэш в памяти не масштабируется. Перейдите в распределенный кэш, например Redis:
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration.GetConnectionString("Redis");
});
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
Распределенный кэш разгружает память из процесса приложения, сохраняет токены между перезапусками и поддерживает развертывания с несколькими экземплярами.
Вариант C. Использование гибридной архитектуры L1/L2
Microsoft. Identity.Web поддерживает гибридный подход, который объединяет быстрый кэш L1 в памяти с постоянным распределенным кэшем L2. Настройте гибридный кэш 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)
};
});
При кэшировании L1/L2 часто запрашиваемые токены извлекаются из памяти (L1) с задержкой менее миллисекунды. Кэш L2 обеспечивает сохраняемость и согласованность между экземплярами. Кэш L1 использует короткие сроки действия, чтобы ограничить рост памяти.
Повторяющиеся запросы MFA или согласия
Симптом
Пользователи неоднократно запрашивают многофакторную проверку подлинности (MFA) или согласие, даже если они недавно выполнили эти действия. Приложение не может найти существующие маркеры в кэше.
Причина
Эта проблема возникает, когда поиск в кэше токенов не удаётся сопоставить кэшированную запись с текущей учетной записью пользователя. Наиболее вероятные причины:
- Ключ кэша отличается от того, который использовался при хранении маркера. Эта ситуация может произойти, если
HomeAccountIdили контекст арендатора изменится. - Приложение выполняет несколько экземпляров за балансировщиком нагрузки с кэшированием в памяти, и запросы направляются к экземпляру, у которого нет токена пользователя.
- Запрашиваемые права или области изменились, в результате чего кэшированный токен не соответствует новому требованию.
- Привязка сеанса не включена, поэтому пользователи направляются в разные экземпляры, которые не имеют кэшированных токенов.
Этапы диагностики
Выполните следующие действия, чтобы определить, почему маркеры не найдены в кэше:
- Проверьте тип кэша. Если вы используете
AddInMemoryTokenCaches()в развертывании с несколькими экземплярами, токены, кэшированные на одном экземпляре, недоступны в другом. Переключитесь в распределенный кэш. - Проверьте идентификатор учетной записи. Включите ведение журнала на уровне отладки и выполните поиск
HomeAccountId. Убедитесь, что идентификатор последователен в разных запросах. - Проверьте области видимости. Убедитесь, что области, запрашиваемые
GetAccessTokenForUserAsync, совпадают с изначально предоставленными областями. Несоответствие области приводит к тому, что MSAL запрашивает новый токен. - Просмотрите политики условного доступа. Политика условного доступа Microsoft Entra ID, требующая поэтапной проверки подлинности для определенных ресурсов, приводит к дополнительным запросам, не связанным с кэшированием.
Решение
Шаг 1. Переключение на распределенное кэширование
Если ваше приложение запускает несколько экземпляров, используйте распределенный кэш для совместного доступа к токенам между экземплярами.
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration.GetConnectionString("Redis");
});
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
Шаг 2. Проверка согласованных областей
Убедитесь, что области, запрашиваемые при получении маркеров, соответствуют областям, настроенным во время проверки подлинности:
// 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" });
Шаг 3. Включение привязки сеанса (временное решение)
Если вы не можете сразу перейти в распределенный кэш, включите сопоставление сеансов (липкие сеансы) в подсистеме балансировки нагрузки. Сходство сеансов направляет запросы пользователя в тот же экземпляр. Этот подход является временным решением с ограничениями масштабируемости.
Проблемы с производительностью кэша
Симптом
Извлечение токенов происходит медленно, а последующие вызовы API увеличивают задержку. Мониторинг показывает высокое среднее время отклика для запросов на получение токенов. Задержка не из-за поставщика удостоверений — токены выдаются из кэша.
Причина
Проблемы с производительностью кэша обычно возникают из:
- Высокая задержка кэша L2. Распределенный кэш находится под тяжелой нагрузкой, географически далеко от приложения или с использованием недостаточного уровня служб.
- Записи кэша больших токенов. Приложения, которые кэшируют маркеры для многих ресурсов на пользователя, могут создавать большие сериализованные записи кэша, которые медленно считываются и записываются.
- Нет кэша L1. Каждое приобретение токена передается в распределенный кэш по сети, даже для токенов, которые часто используются.
Решение
Шаг 1. Включение кэша L1 в памяти
Кэш L1 хранит часто используемые токены в памяти процесса, избегая сетевых запросов в L2.
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.L1CacheOptions = new MsalMemoryTokenCacheOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
SlidingExpiration = TimeSpan.FromMinutes(2)
};
});
С этой конфигурацией токены, обслуживаемые из L1, имеют задержку менее одной миллисекунды. Маркеры, не находящиеся в L1, падают в распределенный кэш L2.
Шаг 2. Оптимизация уровня распределенного кэша
Если задержка кэша L2 высока, рассмотрите следующие действия:
- Увеличьте масштаб экземпляра Redis. Перейдите на более высокий уровень (например, от "Базовый" до "Стандартный" или "Премиум" в Кэш Azure для Redis), чтобы получить большую пропускную способность и снизить задержку.
- Включите георепликацию. Если приложение обслуживает пользователей в нескольких регионах, используйте Кэш Azure для Redis георепликацию, чтобы кэш был близок к вычислительным ресурсам каждого региона.
- Просмотрите конфигурацию сети. Используйте интеграцию Приватный канал или виртуальной сети для уменьшения сетевых прыжков между приложением и кэшем.
Шаг 3. Уменьшение размера сериализованного токена
Если записи кэша токенов большие, проверьте, запрашивает ли приложение токены для большего количества ресурсов, чем необходимо. Каждая уникальная комбинация ресурсов и областей добавляется в размер записи кэша. Консолидируйте вызовы API, где это возможно, чтобы уменьшить количество отдельных маркеров доступа, кэшированных на пользователя.
Вытеснение кэша Redis
Симптом
Пользователям периодически показываются запросы на повторную проверку подлинности, не связанные с определенным шаблоном истечения срока действия маркера. Мониторинг Redis показывает увеличение evicted_keys и used_memory приближение к maxmemory пределу.
Причина
Когда Redis достигает предела maxmemory, он осуществляет удаление ключей на основе настроенного maxmemory-policy. Политикаvolatile-lru по умолчанию () вытесняет последние использованные ключи с истечением срока действия. Если экземпляр Redis разделяется с другими данными приложения, записи кэша маркеров конкурируют за пространство и могут быть преждевременно вытеснены.
Решение
Шаг 1. Проверка политики вытеснения
Проверьте текущую политику вытеснения:
redis-cli CONFIG GET maxmemory-policy
Для кэшей маркеров volatile-lru является подходящим вариантом (по умолчанию), так как записи кэша маркеров имеют срок действия. Однако если другие данные без истечения срока действия занимают память, записи токенов вытесняются первыми.
Шаг 2. Использование выделенного экземпляра Redis
Изоляция кэша маркеров от других данных приложения с помощью выделенного экземпляра 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");
});
Шаг 3. Увеличение ограничения памяти Redis
Если специализированный экземпляр недоступен, увеличьте параметр maxmemory. В Кэш Azure для Redis масштабируйте до более высокого уровня или увеличьте размер кэша.
Шаг 4. Установите соответствующие периоды истечения записей в кэше
Установите разумные сроки действия, чтобы устаревшие записи были удалены до истечения срока действия памяти:
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
options.SlidingExpiration = TimeSpan.FromHours(2);
});
Рост распределенной таблицы кэша SQL
Симптом
Таблица распределенного кэша SQL постоянно растет, потребляя дисковое пространство. Запросы к таблице кэша медленно выполняются со временем и могут отображаться предупреждения о размерах таблиц или ограничениях хранилища.
Причина
Распределенный кэш SQL Server (Microsoft.Extensions.Caching.SqlServer) не удаляет автоматически истекшие записи. Истекшие записи остаются до явной очистки, приводя к неограниченному росту таблицы, снижению производительности запросов и увеличению использования хранилища.
Решение
Шаг 1. Настройка повторяющегося задания очистки
Создайте задание агент SQL Server или запланированную задачу, чтобы периодически удалять истекшие записи:
-- Delete expired entries from the SQL distributed cache table.
-- Schedule this query to run every 30 minutes.
DELETE FROM [dbo].[TokenCache]
WHERE ExpiresAtTime < GETUTCDATE();
Подсказка
В База данных SQL Azure, где агент SQL Server недоступен, используйте Cлужба автоматизации Azure, Функции Azure с триггером таймера или Elastic Jobs для планирования очистки.
Шаг 2. Добавление индекса для эффективной очистки
Если в таблице кэша еще нет индекса в столбце окончания срока действия, добавьте его, чтобы ускорить операцию удаления:
CREATE NONCLUSTERED INDEX IX_TokenCache_ExpiresAtTime
ON [dbo].[TokenCache] (ExpiresAtTime);
Шаг 3. Мониторинг размера таблицы
Добавьте мониторинг для отслеживания количества строк и размера таблицы с течением времени:
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];
Шаг 4. Рассмотрите возможность переключения на Redis
Если управление очисткой кэша SQL является обременительным, переключитесь на Redis, которая автоматически обрабатывает срок действия через встроенный механизм TTL:
// Replace SQL distributed cache with Redis.
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration.GetConnectionString("Redis");
});
Общие советы по устранению неполадок
Используйте эти советы, если проблема не соответствует определенному сценарию в этой статье.
Проверка использования кэша
Добавьте временный журнал, чтобы подтвердить, что токены считываются и записываются в кэш.
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;
};
});
Проверка нескольких регистраций кэша
Если в коде запуска существует несколько вызовов AddInMemoryTokenCaches() или AddDistributedTokenCaches(), последняя регистрация имеет приоритет. Убедитесь, что зарегистрирован только один тип кэша.
Проверка срока службы токена
Маркеры доступа имеют конечное время существования (обычно 60–90 минут). Если пользователи сообщают о повторной проверке подлинности после этого периода, это является ожидаемым поведением, а не проблемой с кэшем. Токены обновления обеспечивают получение новых токенов доступа в фоновом режиме и хранятся в кэше. Если маркер обновления отсутствует или истек, пользователь должен повторно пройти проверку подлинности.
Тестирование с помощью чистого кэша
При диагностике проблем снимите кэш, чтобы исключить поврежденные или устаревшие записи:
- Кэш в памяти: Перезапустите приложение.
-
Redis: Выполните
FLUSHDBв базе данных кэша. - SQL Server: Удалите все строки из таблицы кэша.
Кэш токенов пуст после перезапуска приложения
Симптом
Пользователи должны повторно пройти проверку подлинности после каждого перезапуска или повторного развертывания приложения. Распределенный кэш отображается пустым или маркеры не сохраняются.
Причина
Эта проблема обычно возникает при использовании кэша в памяти (AddInMemoryTokenCaches()) или не постоянного распределенного кэша памяти (AddDistributedMemoryCache()) в рабочей среде. Ни один из вариантов не сохраняет токены при перезапуске приложения.
AddDistributedMemoryCache() регистрирует реализацию IDistributedCache , в которой хранятся данные в памяти. Несмотря на "распределенное" имя, оно не сохраняет данные внешне и предназначено только для разработки и тестирования.
Решение
Переключитесь в постоянный распределенный кэш:
// 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();
Предупреждение
Не путайте AddDistributedMemoryCache() с постоянным распределенным кэшем. Используйте AddStackExchangeRedisCache() (Redis), AddDistributedSqlServerCache() (SQL Server) или другую постоянную реализацию IDistributedCache для рабочих нагрузок.