Blazor Server端2分钟无操作后未跳转登录页问题排查
Blazor Server 无操作超时跳转失效问题排查与修复
以下是导致超时逻辑失效的核心问题及对应的修复方案:
1. .NET Ticks 格式无法被JS正确解析
你在C#中存储的DateTime.Now.Ticks.ToString()是.NET专属的时间格式,JS的Date.parse()无法识别该格式,会返回NaN。这会导致lastActivity变成无效日期,new Date() - lastActivity的计算结果永远是NaN,无法触发超时判断。
修复代码:
将C#中的时间存储改为JS可识别的ISO格式:
protected override async Task OnInitializedAsync() { // 存储UTC标准ISO格式时间,确保JS能正确解析 await JS.InvokeVoidAsync("sessionStorage.setItem", "LastActivity", DateTime.Now.ToUniversalTime().ToString("o")); }
2. 未监听用户操作以更新超时时间
当前代码仅在页面初始化时设置一次LastActivity,用户后续的点击、输入、滚动等操作不会刷新超时时间——即使用户一直在操作,到2分钟也会触发跳转,反之如果用户未操作但初始时间解析错误,也无法触发跳转。
修复代码:
在JS中添加用户操作监听,实时更新LastActivity:
// 监听所有常见用户操作事件 const activityEvents = ['mousedown', 'keydown', 'scroll', 'touchstart']; // 更新最后活动时间 function updateLastActivity() { sessionStorage.setItem("LastActivity", new Date().toISOString()); } // 绑定事件监听 activityEvents.forEach(event => { document.addEventListener(event, updateLastActivity); }); // 原有超时检查函数修正 function checkSessionTimeout(currentUrl) { const sessionTimeout = 2 * 60 * 1000; const lastActivityStr = sessionStorage.getItem("LastActivity"); // 无记录或日期无效时直接跳转 if (!lastActivityStr || isNaN(new Date(lastActivityStr).getTime())) { sessionStorage.clear(); window.location.href = `/login?returnUrl=${encodeURIComponent(currentUrl)}`; return; } const lastActivity = new Date(lastActivityStr); if (new Date() - lastActivity > sessionTimeout) { sessionStorage.clear(); window.location.href = `/login?returnUrl=${encodeURIComponent(currentUrl)}`; } else { setTimeout(() => checkSessionTimeout(currentUrl), 1000); } } // 初始化时先设置一次活动时间,再启动检查 updateLastActivity(); checkSessionTimeout(window.location.href);
3. 异步调用顺序与重复检查问题
OnInitialized是同步方法,但JS.InvokeVoidAsync是异步操作,可能出现checkSessionTimeout已经启动,但LastActivity还未写入sessionStorage的情况。- 多次调用
checkSessionTimeout会导致多个定时器同时运行,逻辑混乱。
修复方案:
- 将C#中的
OnInitialized改为异步方法(如上述代码所示),确保时间写入完成后再执行后续逻辑。 - 在JS中添加全局标记,避免重复启动检查:
let isCheckerRunning = false; function checkSessionTimeout(currentUrl) { if (isCheckerRunning) return; isCheckerRunning = true; // ...原有检查逻辑... setTimeout(() => { isCheckerRunning = false; checkSessionTimeout(currentUrl); }, 1000); }
4. 额外验证点
- 打开浏览器开发者工具(F12),切换到
Application标签,检查sessionStorage中是否存在LastActivity项,确认格式是否为ISO字符串。 - 如果页面在iframe中运行,需确认是否存在跨域存储限制。
- 若需求是**页面切换到后台(最小化/切标签)**后超时,需额外监听
visibilitychange事件:
document.addEventListener('visibilitychange', () => { if (document.hidden) { updateLastActivity(); } });
内容的提问来源于stack exchange,提问作者ahmed abdelaziz
相关产品推荐
相关产品推荐

