无粘性会话的负载均衡服务器上ASP.NET Core 6 Razor Pages问题求助
ASP.NET Core 6 Razor应用在无粘性会话负载均衡环境下的登录及页面空白问题
问题描述
将ASP.NET Core 6 Razor应用部署到两台无粘性会话的负载均衡服务器后,出现以下异常:
- 登录页空白(黑屏)
- 登录后页面空白(黑屏)
- 登录应用后执行操作触发错误请求
部分场景下刷新页面可临时恢复,但执行任意操作后问题会再次出现。服务器已配置HTTPS,无此类环境部署经验,尝试过Cookie配置、Redis分布式缓存、会话验证中间件、请求转发配置等方案,问题未解决。
相关代码
Program.cs 配置代码
RedisCacheOptions cacheoptions = new RedisCacheOptions() { Configuration = conn, InstanceName = "SampleInstance" + Guid.NewGuid() }; builder.Services.AddDistributedRedisCache(options => { options = cacheoptions; }); builder.Services.Configure<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme, options => { options.Cookie.Name = "MyWebsite"; }); builder.Services.Configure<CookiePolicyOptions>(options => { options.CheckConsentNeeded = context => false; options.MinimumSameSitePolicy = SameSiteMode.None; }); builder.Services.ConfigureApplicationCookie(options => { options.Cookie.HttpOnly = true; options.Cookie.SameSite = SameSiteMode.None; options.Cookie.MaxAge = TimeSpan.FromHours(5); options.SlidingExpiration = true; options.LogoutPath = $"/Licencias/Logout"; options.AccessDeniedPath = $"/Account/AccessDenied"; }); builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options => { options.LoginPath = "/Login/Index"; options.AccessDeniedPath = "/Account/AccessDenied"; options.Events.OnSigningOut = (context) => { context.Response.Redirect("/Login/Index"); return Task.CompletedTask; }; });
应用中间件配置代码
app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedProto }); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseMiddleware<ValidarSesionMiddleware>(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseCookiePolicy();
解决方案
1. 修复Redis分布式缓存配置错误
原Redis配置的赋值逻辑无效,且InstanceName动态生成Guid会导致多服务器无法共享缓存数据,修改为:
builder.Services.AddDistributedRedisCache(options => { options.Configuration = conn; options.InstanceName = "SampleInstance"; // 固定实例名称,确保多服务器共享缓存 });
2. 配置跨服务器数据保护共享
无粘性会话环境下,必须让多服务器共享数据保护密钥,否则无法识别彼此生成的认证Cookie:
// 确保已安装StackExchange.Redis NuGet包 builder.Services.AddDataProtection() .PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(conn), "DataProtection-Keys") .SetApplicationName("MyRazorApp"); // 所有服务器使用相同的应用名称
3. 调整中间件执行顺序
中间件顺序错误会导致Cookie策略、认证逻辑无法正常生效,修正为:
// 配置负载均衡IP白名单,避免恶意请求滥用转发头 app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto, KnownProxies = { IPAddress.Parse("负载均衡服务器IP1"), IPAddress.Parse("负载均衡服务器IP2") } }); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); // 移至认证中间件之前 app.UseMiddleware<ValidarSesionMiddleware>(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization();
4. 完善认证Cookie安全配置
HTTPS环境下强制Cookie的Secure属性,统一配置避免冲突:
builder.Services.ConfigureApplicationCookie(options => { options.Cookie.HttpOnly = true; options.Cookie.SameSite = SameSiteMode.None; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // HTTPS下强制Secure options.Cookie.MaxAge = TimeSpan.FromHours(5); options.SlidingExpiration = true; options.LogoutPath = "/Licencias/Logout"; options.AccessDeniedPath = "/Account/AccessDenied"; options.LoginPath = "/Login/Index"; // 统一配置登录路径 }); builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.Events.OnSigningOut = (context) => { context.Response.Redirect("/Login/Index"); return Task.CompletedTask; }; });
5. 排查自定义会话验证中间件
临时注释ValidarSesionMiddleware,测试问题是否消失。若问题缓解,检查中间件逻辑是否依赖本地会话存储、未正确处理分布式缓存数据,或在无粘性环境下错误校验会话状态。
6. 确保静态文件一致性
确认两台服务器的静态文件(CSS、JS、图片)完全一致,或使用CDN统一分发静态资源,避免浏览器加载到损坏/不一致的资源导致页面空白。
内容的提问来源于stack exchange,提问作者Leo Nunez
相关产品推荐
相关产品推荐

