在.NET 5的Startup.cs中能否从DbContext取值设置Cookie的ExpireTimeSpan
解决方案
有两种主流实现方式,推荐优先选择第一种,支持配置动态生效无需重启应用:
方式1:登录时动态配置Cookie过期时间(推荐)
利用CookieAuthenticationEvents的OnSigningIn事件,在每次用户登录时实时读取数据库配置,无需在应用启动阶段读取配置,也不会触发服务容器构建警告:
- 修改
ConfigureServices中的ConfigureApplicationCookie配置,替换为如下代码:
services.ConfigureApplicationCookie(options => { options.SlidingExpiration = true; options.Events = new CookieAuthenticationEvents { OnSigningIn = async context => { // 从当前请求的作用域容器中获取Scoped服务,无需手动构建服务提供器 var settingsService = context.HttpContext.RequestServices.GetRequiredService<CustomerSettingsService>(); // 从数据库读取自定义的过期分钟数 int expireMinutes = await settingsService.Get(); // 覆盖默认过期时间 context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(expireMinutes); } }; });
该方案优势:数据库中的过期配置修改后,新登录的用户会直接生效,无需重启应用。
方式2:启动时一次性读取配置
如果只需要在应用启动时读取一次配置,后续不会修改,可以通过自定义选项配置类实现:
- 新增配置类实现
IConfigureOptions<CookieAuthenticationOptions>:
public class CookieOptionConfigurator : IConfigureOptions<CookieAuthenticationOptions> { private readonly IServiceScopeFactory _scopeFactory; // 注入作用域工厂,用于手动创建Scoped服务的作用域 public CookieOptionConfigurator(IServiceScopeFactory scopeFactory) { _scopeFactory = scopeFactory; } public void Configure(CookieAuthenticationOptions options) { // 手动创建作用域读取Scoped服务 using var scope = _scopeFactory.CreateScope(); var settingsService = scope.ServiceProvider.GetRequiredService<CustomerSettingsService>(); int expireMinutes = settingsService.Get().GetAwaiter().GetResult(); options.ExpireTimeSpan = TimeSpan.FromMinutes(expireMinutes); options.SlidingExpiration = true; } }
- 在
ConfigureServices中注册该配置类,删除原来的ConfigureApplicationCookie配置:
// 注册自定义Cookie配置类 services.AddSingleton<IConfigureOptions<CookieAuthenticationOptions>, CookieOptionConfigurator>(); // 原有Identity注册逻辑保持不变 services .AddDefaultIdentity<IdentityUser>() .AddEntityFrameworkStores<IdentityDataContext>();
原错误原因说明
- 在
ConfigureServices中调用BuildServiceProvider会创建额外的独立服务容器,导致单例服务出现多个副本,引发状态不一致问题,因此官方会抛出警告。 Configure方法用于构建中间件管道,Cookie认证的配置在管道构建完成后无法直接修改,因此无法在该方法中调整ExpireTimeSpan。
内容的提问来源于stack exchange,提问作者Andres Elizondo
相关产品推荐
相关产品推荐

