Cookie身份验证提前过期

5

问题

在我的ASP.NET MVC Core 2.0应用程序中,我已经设置了使用cookie身份验证方案,而不使用Identity,因为我们有自己的后端身份验证存储和api。

每次身份验证和授权都能完美地工作。

然而,无论何时登录/会话都会在大约30分钟后过期。您可以看到我们将超时时间设置为120分钟,用于身份验证cookie和会话cookie。

应用程序信息:

  • 平台:.Net 4.7.x(Windows)
  • 框架:Asp.Net Core 2.x
  • IIS用作代理服务器

欢迎提供任何帮助或意见以解决此问题

代码

更新:使用services.AddDistributedRedisCache(..)替换了services.AddMemoryCache() - 测试其效果

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddDistributedRedisCache(options =>
        {
            options.Configuration = "localhost";
            options.InstanceName = "CoreTestInstance";
        });

    services.AddAuthentication("CookieAuthenticationScheme")
        .AddCookie("CookieAuthenticationScheme", options => 
        {
            options.Cookie.Name = authSettings.Name;
            options.Cookie.HttpOnly = false;
            options.Cookie.Expiration = TimeSpan.FromMinutes(120);
            options.ExpireTimeSpan = TimeSpan.FromMinutes(120);
            options.AccessDeniedPath = new PathString("/Errors/StatusCodeErrors/401");
            options.LoginPath = "/Account/Login";
        });
        // services.AddMemoryCache();
        services.AddSession(options =>
        {
            options.Cookie.Name = sessSettings.Name;
            options.Cookie.HttpOnly = false;
            options.IdleTimeout = TimeSpan.FromMinutes(120);
        });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Errors/Default");
    }
    app.UseStatusCodePagesWithRedirects("/Errors/StatusCodeErrors/{0}");
    app.UseStaticFiles();
    app.UseAuthentication();
    app.UseSession();
    app.UseMvc();
}

AccountController.cs

[HttpPost("Login")]
public async Task<IActionResult> Login(AccountModel model)
{
    var claims = new List<Claim>();
    claims.Add(new Claim(ClaimTypes.Name, model.UserName));
    claims.Add(new Claim(ClaimTypes.Role, "Administrator", ClaimValueTypes.String, model.UserName));

    var identity = new ClaimsIdentity(claims, "login");
    var principal = new ClaimsPrincipal(identity);
    await HttpContext.SignInAsync("CookieAuthenticationScheme", principal);
}
2个回答

3

您正在使用内存会话,这些会话与进程绑定。在 IIS 中,该进程是您的应用池。默认情况下,应用程序池在一段时间后会自动重新启动。重新启动时,会将您的会话一起带走。

请使用持久化会话存储:SQL Server、Redis 等(会话使用分布式缓存,因此设置持久化会话的方法是设置持久化分布式缓存存储)。


这是正确的,然而应用程序池到期时间设置为300分钟,且存在相同的行为。不过,我会研究一下持久化会话,并看看它是否适合我们。 - Tab
总的来说,在生产环境中,你永远不应该使用内存中的任何东西。无论它是否解决了这个问题,你都应该使用持久化存储。 - Chris Pratt
好主意,通常我们在生产中使用SQL Server,我会在我的开发环境中试一下。 - Tab

0

感谢 Chris Pratt 指导我走上了正确的道路。转向使用 Redis 提高了性能,分布式缓存也是正确的选择。

然而,Redis 并没有解决我的问题,无论设置如何,应用程序仍在90分钟后超时。

由于我们使用的是 IIS,最终我不得不更改 AppPool 中的设置才能使会话遵守我的超时而非 AppPool 的超时。

  • 对于 AppPool,请单击“高级设置”并进行以下更改:
    • 部分:进程模型
      • 空闲超时(分钟)= 0(禁用超时,以便应用程序池永远不会因空闲而关闭)
      • 空闲超时操作= 暂停(暂停的工作进程仍然存活,但已被页面换出到磁盘中,从而减少了其消耗的系统资源)
    • 部分:回收
      • 定期时间间隔(分钟)= 0(将其设置为0表示 apppool 不会回收)

注意:上述设置不应影响其他应用程序,除非您在同一服务器上运行了大量应用程序。我建议您在使用这些设置之前详细研究它们,以确保它们适合您的需求。

最后,我使用各种设置(我们将它们存储在appsettings.json中)进行了几次测试,包括2分钟、10分钟、1小时和最终的2小时超时,并且所有测试都按要求正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接