You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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会导致多个定时器同时运行,逻辑混乱。

修复方案:

  1. 将C#中的OnInitialized改为异步方法(如上述代码所示),确保时间写入完成后再执行后续逻辑。
  2. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 15:13:01