ASP.NET Core 8中AddDistributedSqlServerCache的DefaultSlidingExpiration不生效
ASP.NET Core 8中AddDistributedSqlServerCache的DefaultSlidingExpiration未生效的解决办法
问题根源
AddDistributedSqlServerCache配置的DefaultSlidingExpiration是分布式缓存本身的默认过期策略,仅当调用IDistributedCache存储数据时未指定过期时间才会生效。但Cookie认证在将票据存储到分布式缓存时,会默认使用自身配置的ExpireTimeSpan(默认20分钟=1200秒)覆盖缓存的默认值,因此你设置的90分钟不会生效。
解决步骤
1. 确保Cookie认证使用分布式缓存存储票据
如果你的Cookie认证原本将票据直接存在Cookie中,分布式缓存的配置不会产生任何影响,必须先配置Cookie使用分布式缓存存储票据:
// 注册分布式缓存票据存储(需引用Microsoft.AspNetCore.Authentication.Cookies) builder.Services.AddSingleton<ITicketStore, DistributedCacheTicketStore>();
2. 同步过期策略(两种可选方案)
方案一:显式对齐Cookie与缓存的过期时间
直接在Cookie认证配置中设置与缓存一致的过期时间,确保两者同步:
builder.Services.AddAuthentication(options => { // 配置默认认证方案等逻辑... }) .AddCookie(options => { // 开启滑动过期 options.SlidingExpiration = true; // 设置与缓存默认值一致的过期时间 options.ExpireTimeSpan = TimeSpan.FromMinutes(90); // 指定使用分布式缓存存储票据 options.SessionStore = builder.Services.BuildServiceProvider().GetRequiredService<ITicketStore>(); }) .AddOpenIdConnect(options => { // OIDC相关配置... });
方案二:让TicketStore自动使用缓存的默认过期值
如果不想硬编码过期时间,可以自定义TicketStore,让它读取分布式缓存的DefaultSlidingExpiration配置:
public class CustomDistributedCacheTicketStore : DistributedCacheTicketStore { private readonly SqlServerCache _sqlServerCache; public CustomDistributedCacheTicketStore(IDistributedCache cache, ILoggerFactory loggerFactory) : base(cache, loggerFactory) { _sqlServerCache = cache as SqlServerCache; } public override async Task<string> StoreAsync(AuthenticationTicket ticket) { var key = await base.StoreAsync(ticket); // 使用缓存配置的默认滑动过期时间 var cacheOptions = new DistributedCacheEntryOptions { SlidingExpiration = _sqlServerCache?.Options.DefaultSlidingExpiration ?? TimeSpan.FromMinutes(90) }; await _sqlServerCache.RefreshAsync(key, cacheOptions); return key; } } // 注册自定义TicketStore builder.Services.AddSingleton<ITicketStore, CustomDistributedCacheTicketStore>();
然后在Cookie认证中配置:
.AddCookie(options => { options.SlidingExpiration = true; // 不设置ExpireTimeSpan,让TicketStore使用缓存的默认值 options.SessionStore = builder.Services.BuildServiceProvider().GetRequiredService<ITicketStore>(); })
内容的提问来源于stack exchange,提问作者Matthew S
相关产品推荐
相关产品推荐

