ASP.NET Core 6会话超时服务器不生效及过期跳转登录页问题
ASP.NET Core 6会话超时配置问题及解决方案
问题描述
我正在调整ASP.NET Core 6项目,将会话超时设置为50分钟(微软文档显示默认超时为20分钟)。本地测试时,会话50分钟过期后会跳转至应用错误页,但部署到服务器后,会话仍在默认20分钟时过期。请问如何实现50分钟会话超时,并在会话过期后刷新页面时跳转至登录页而非错误页?
我的代码
Program.cs
using OtherSportsMaster; namespace OtherSportsMaster { public class Program { public static void Main(string[] args) { var host = new WebHostBuilder() .UseKestrel(options => { options.Limits.MaxRequestBodySize = null; }) .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .UseUrls("http://localhost:5001") .Build(); host.Run(); //CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); } }
Startup.cs
using OtherSportsMaster.Data; using OtherSportsMaster.Models; using OtherSportsMaster.Models.MasterDAL; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Server.IIS; using System.Data.Common; using Microsoft.Extensions.Options; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Authorization; namespace OtherSportsMaster { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; //BundleConfig.RegisterBundles(BundleTable.Bundles); } public IConfiguration Configuration { get; } // 运行时调用此方法向容器添加服务 public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(IISServerDefaults.AuthenticationScheme); services.AddHttpContextAccessor(); services.AddDistributedMemoryCache(); // 设置会话超时,默认20分钟 services.AddSession(options => { //options.Cookie.Name = ".AspNetCore.Session"; options.IdleTimeout = TimeSpan.FromMinutes(50); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); //.AddDistributedMemoryCache(); services.AddControllersWithViews(); //services.AddRazorPages(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddScoped<CommanCls>(); services.AddScoped<DBConnectionCls>(); services.AddMvc(option => option.EnableEndpointRouting = false); services.Configure<IISServerOptions>(options => { options.MaxRequestBodySize = int.MaxValue; }); //services.Configure<FormOptions>(x => //{ // x.ValueLengthLimit = int.MaxValue; // x.MultipartBodyLengthLimit = int.MaxValue; // x.MultipartHeadersLengthLimit = int.MaxValue; // x.ValueCountLimit = 10; // x.MemoryBufferThreshold = Int32.MaxValue; //}); //services.AddMvc(); //services.AddMvc(options => //{ // options.Filters.Add(typeof(AuthorizeAttribute)); // options.MaxModelBindingCollectionSize = int.MaxValue; //}); } // 运行时调用此方法配置HTTP请求管道 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); //app.UseHsts(); } //app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseSession(); app.UseMvc(); AppHttpContext.Services = app.ApplicationServices; //app.Use(async (context, next) => //{ // context.Features.Get<IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize = null; // unlimited I guess // await next.Invoke(); //}); //app.UseEndpoints(endpoints => //{ // endpoints.MapControllerRoute( // name: "default", // pattern: "{controller=Login}/{action=Index}/{id?}"); //}); //app.UseMvc(ConfigureRoute); // app.UseMvcWithDefaultRoute(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Master}/{action=Login}/{id?}"); }); //app.Run(async (context) => //{ // await context.Response.WriteAsync("\"No "); //}); } } }
web.config
<?xml version="1.0" encoding="utf-8"?> <configuration> <location path="." inheritInChildApplications="false"> <system.web> <httpRuntime maxRequestLength="1048576" /> </system.web> <system.webServer> <security> <requestFiltering> <requestLimits maxUrl="65536" maxQueryString="2097151" maxAllowedContentLength="4294967295" /> <!-- 1 GB--> <!-- ~ 4GB --> </requestFiltering> </security> <handlers> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" /> </handlers> <aspNetCore requestTimeout="00:50:00" processPath=".\OtherSportsMaster.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" /> </system.webServer> <system.web.extensions> <scripting> <webServices> <jsonSerialization maxJsonLength="86753090"/> </webServices> </scripting> </system.web.extensions> </location> </configuration> <!--ProjectGuid: ac80560e-7b73-4211-994b-881b5818045d-->
解决方案
一、解决服务器端会话20分钟过期问题
服务器上会话提前过期的核心原因是IIS应用池闲置超时回收,默认应用池闲置20分钟会自动回收进程,导致内存中的Session数据丢失。
调整IIS应用池闲置超时
- 打开IIS管理器,找到对应应用的应用池
- 右键选择“高级设置”
- 找到“闲置超时(分钟)”,设置为大于50分钟(比如55分钟),或者设为0表示永不回收(生产环境需根据实际运维情况调整)
完善Session配置
在Startup.cs的ConfigureServices方法中,给Session Cookie添加过期时间,确保和IdleTimeout一致:services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(50); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; options.Cookie.Expires = TimeSpan.FromMinutes(50); // 新增此行,同步Cookie过期时间 });确认中间件顺序
当前Configure方法中app.UseSession()在app.UseMvc()之前,这个顺序是正确的,不要调整,确保Session中间件先于MVC执行。
二、实现会话过期跳转登录页而非错误页
通过自定义全局过滤器来检查会话状态,避免跳转到错误页:
创建会话检查过滤器
在项目中新增一个类:using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; namespace OtherSportsMaster { public class SessionCheckFilter : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { // 替换为你实际判断用户登录状态的Session键 var userInfo = context.HttpContext.Session.GetString("UserInfo"); if (string.IsNullOrEmpty(userInfo)) { // 排除登录页面,防止循环跳转 var controller = context.RouteData.Values["controller"]?.ToString() ?? ""; var action = context.RouteData.Values["action"]?.ToString() ?? ""; if (!controller.Equals("Master", StringComparison.OrdinalIgnoreCase) || !action.Equals("Login", StringComparison.OrdinalIgnoreCase)) { // 跳转到登录页 context.Result = new RedirectToRouteResult(new RouteValueDictionary { { "controller", "Master" }, { "action", "Login" } }); } } base.OnActionExecuting(context); } } }注册全局过滤器
在Startup.cs的ConfigureServices方法中,修改AddMvc的配置,添加过滤器:services.AddMvc(option => { option.EnableEndpointRouting = false; option.Filters.Add(typeof(SessionCheckFilter)); // 注册会话检查过滤器 });调整错误页逻辑
非开发环境下的app.UseExceptionHandler("/Home/Error")仅处理系统异常,会话过期的情况已经由过滤器处理,不会再触发错误页跳转。
注意事项
- 如果服务器部署了多实例应用,建议使用分布式缓存(如Redis)替代
DistributedMemoryCache,避免Session数据无法共享。 - 确保服务器上的.NET Core运行时版本和项目目标版本一致。
内容的提问来源于stack exchange,提问作者Ashik Sp
相关产品推荐
相关产品推荐

