ASP.NET Core:调用KeepSessionAlive后会话超时仍无法访问控制器
问题分析与解决方案
核心问题根源
你遇到的400错误本质是Anti-Forgery Token(请求Token)与对应Cookie不匹配。虽然KeepSessionAlive能刷新会话并返回新的请求Token,但由于以下原因,Token与Cookie无法完成配对验证:
- Fetch请求未携带会话凭证:默认情况下
fetch的凭证策略未明确设置,导致请求未携带当前会话的Cookie。服务器无法识别现有会话,每次KeepSessionAlive都会生成全新的Anti-Forgery Cookie和请求Token,客户端保存的旧Cookie与新请求Token无法匹配。 - Anti-Forgery Cookie未配置滑动过期:你给Session开启了
SlidingExpiration(活动时刷新过期时间),但Anti-Forgery Cookie默认未开启该配置,即使会话被刷新,Cookie的绝对过期时间不会更新,若出现浏览器缓存或配置生效异常,会提前导致Cookie失效。 - Token覆盖不完整:仅更新表单中的
__RequestVerificationToken可能存在遗漏,比如部分AJAX请求通过Header传递Token,未同步更新会触发验证失败。
具体解决方案
1. 修正Fetch请求的凭证策略
在客户端fetch请求中明确添加credentials: 'same-origin',确保请求携带当前会话的Cookie,让服务器关联到现有会话,生成匹配的Token和Cookie:
fetch('/Home/KeepSessionAlive', { method: 'GET', headers: { 'Accept': 'application/json' }, credentials: 'same-origin' // 新增此行,确保携带会话Cookie })
2. 给Anti-Forgery Cookie开启滑动过期
在Program.cs的Anti-Forgery配置中添加SlidingExpiration = true,让Cookie的过期时间随用户活动自动刷新,与Session保持一致:
builder.Services.AddAntiforgery(options => { options.Cookie.Name = ".AspNetCore.Antiforgery"; options.Cookie.HttpOnly = true; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.Cookie.MaxAge = TimeSpan.FromMinutes(720); options.Cookie.SlidingExpiration = true; // 开启滑动过期 });
3. 确保Session中间件顺序正确
检查Program.cs中中间件的注册顺序,UseSession必须在UseRouting之后、UseAuthorization之前,否则会话无法正常工作:
app.UseRouting(); app.UseSession(); // 位置正确才能确保会话正常生效 app.UseAuthorization(); // ...其他中间件
4. 统一Token更新逻辑(可选)
如果存在AJAX POST请求,除了更新表单input,还需全局设置请求Header,确保所有POST请求都携带最新的Token:
// 更新表单Token的同时,设置全局请求Header document.querySelector('input[name="__RequestVerificationToken"]').value = data.antiForgeryToken; // 示例:为axios请求设置默认Header axios.defaults.headers.common['RequestVerificationToken'] = data.antiForgeryToken;
验证步骤
- 修改完成后,打开浏览器开发者工具的Application标签,查看
Cookies下的.AspNetCore.Antiforgery和.AspNetCore.Session的过期时间,每次调用KeepSessionAlive后,两者的过期时间应被刷新。 - 等待一小时后发起POST请求,检查请求头中是否携带了正确的Cookie和RequestToken,验证是否能正常进入
SaveProjectDetails方法。
内容的提问来源于stack exchange,提问作者Shane
相关产品推荐
相关产品推荐

