Identity Server 分布式缓存无法正常工作问题求助
核心问题原因
1. 组件作用匹配错误
AddOidcStateDataFormatterCache是给作为OIDC客户端的应用设计的,用于缓存OIDC授权请求过程中的state、nonce、code_verifier等临时数据。你当前的服务是IDS4身份提供方(IDP)本身,注册的AddIdentityServerAuthentication仅用于保护当前服务的API接口,并不会作为客户端发起OIDC授权流程,因此这个扩展无论是否指定Scheme,都不会在你的登录流程中被触发。
2. Cookie存储逻辑认知偏差
ASP.NET Core Identity默认签发的登录Cookie是自包含的加密票证,所有用户身份信息加密后直接存储在客户端Cookie中,服务端默认不会将票证副本写入分布式缓存。你看到有数据写入的dbo.PersistedGrants表仅存储IDS4的授权码、刷新令牌、参考令牌等授权相关数据,和登录Cookie无关。
3. 分布式缓存本身配置正常
你手动注入IDistributedCache写入数据成功,说明数据库分布式缓存的基础配置完全正确,问题是没有相关组件在登录流程中主动调用缓存写入接口。
解决方案
根据你的实际需求选择对应配置即可:
场景1:需要将登录Cookie票证存储到分布式缓存(实现服务端主动失效Cookie的能力)
给Identity的ApplicationCookie显式配置基于分布式缓存的ITicketStore实现,示例代码如下:
// 先实现分布式缓存票证存储类 public class DistributedCacheTicketStore : ITicketStore { private readonly IDistributedCache _cache; private readonly ITicketDataFormat _format; private const string KeyPrefix = "AuthTicket_"; public DistributedCacheTicketStore(IDistributedCache cache, ITicketDataFormat format) { _cache = cache; _format = format; } public async Task<string> StoreAsync(AuthenticationTicket ticket) { var key = KeyPrefix + Guid.NewGuid().ToString("N"); var ticketData = _format.Protect(ticket); await _cache.SetStringAsync(key, ticketData, new DistributedCacheEntryOptions { AbsoluteExpiration = ticket.Properties.ExpiresUtc }); return key; } public async Task<AuthenticationTicket> RetrieveAsync(string key) { var ticketData = await _cache.GetStringAsync(key); return ticketData == null ? null : _format.Unprotect(ticketData); } public async Task RenewAsync(string key, AuthenticationTicket ticket) { var ticketData = _format.Protect(ticket); await _cache.SetStringAsync(key, ticketData, new DistributedCacheEntryOptions { AbsoluteExpiration = ticket.Properties.ExpiresUtc }); } public async Task RemoveAsync(string key) { await _cache.RemoveAsync(key); } } // 然后在ConfigureApplicationCookie中注册 services.ConfigureApplicationCookie(options => { options.ExpireTimeSpan = TimeSpan.FromSeconds(55); options.SlidingExpiration = false; // 新增配置,使用分布式缓存存票证 options.SessionStore = new DistributedCacheTicketStore( services.BuildServiceProvider().GetRequiredService<IDistributedCache>(), new TicketDataFormat( services.BuildServiceProvider().GetRequiredService<IDataProtectionProvider>() .CreateProtector("Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", IdentityConstants.ApplicationScheme, "v2")) ); });
配置后客户端Cookie仅存储票证ID,完整票证内容会自动写入你配置的分布式缓存表。
场景2:需要将IDS4内部临时数据存储到分布式缓存
IDS4默认使用内存缓存存储授权请求上下文、登出上下文等临时数据,你只需要在IDS4注册配置中添加AddDistributedCacheTokenStorage扩展即可:
services.AddIdentityServer(Ids4Options()) .AddAspNetIdentity<AppUser>() .AddOperationalStore(OperationOptions()) .AddConfigurationStore(ConfigOptions()) .AddProfileService<ProfileService>() .AddDeveloperSigningCredential() // 新增这行,配置IDS4用分布式缓存存临时数据 .AddDistributedCacheTokenStorage();
配置后IDS4的相关临时数据会自动写入分布式缓存表。
内容的提问来源于stack exchange,提问作者Konrad Viltersten

