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

基于AddMicrosoftIdentityWebApp的Azure AD会话过期前端检测方案咨询

实现Razor页面会话过期前提示的可行方案

针对Azure AD单点登录+Session IdleTimeout=1分钟的场景,前端检测并提示会话即将过期可以通过后端传递超时参数+前端定时器监控用户活动的方式实现,以下是具体步骤和代码示例:

方案一:基于Session IdleTimeout的基础提示实现

1. 后端传递Session超时时间到前端

在Razor页面的PageModel中,将Session的超时时间转换为毫秒值,传递给前端视图:

public class HomeModel : PageModel
{
    // 存储Session超时毫秒数,供前端使用
    public int SessionTimeoutMs { get; set; }

    public void OnGet()
    {
        // 从HttpContext获取Session的IdleTimeout,转换为毫秒
        SessionTimeoutMs = (int)HttpContext.Session.IdleTimeout.TotalMilliseconds;
    }
}

2. 前端定时器监控与提示逻辑

在Razor页面的脚本中,实现定时器监控、用户活动重置、会话延长和过期跳转逻辑:

<script>
    // 从后端获取Session超时毫秒数,提前10秒触发提示
    const sessionTimeoutMs = @Model.SessionTimeoutMs;
    const warningAdvanceMs = 10000;
    let warningTimer;
    let expireTimer;

    // 重置所有定时器的核心函数
    function resetSessionTimers() {
        // 清除现有定时器
        clearTimeout(warningTimer);
        clearTimeout(expireTimer);

        // 设置提示定时器:超时前10秒触发
        warningTimer = setTimeout(() => {
            // 用自定义模态框或原生confirm提示用户
            if (confirm('会话即将过期,是否点击确认延长会话?')) {
                // 发起后端请求刷新Session(需确保请求携带Cookie)
                fetch('/KeepAlive', { method: 'POST', credentials: 'include' })
                    .then(res => {
                        if (res.ok) resetSessionTimers(); // 刷新成功后重置定时器
                    });
            } else {
                // 用户选择不延长,等待会话过期后跳转登录页
                expireTimer = setTimeout(() => {
                    alert('会话已过期,请重新登录');
                    window.location.href = '/Account/Login';
                }, warningAdvanceMs);
            }
        }, sessionTimeoutMs - warningAdvanceMs);
    }

    // 监听用户活跃事件(鼠标移动、键盘输入),重置定时器
    document.addEventListener('mousemove', resetSessionTimers);
    document.addEventListener('keydown', resetSessionTimers);

    // 页面加载时初始化定时器
    window.addEventListener('load', resetSessionTimers);
</script>

3. 后端实现会话刷新端点

添加一个用于刷新Session的Razor页面或API端点,只要用户访问该端点,Session的IdleTimeout就会重置:

public class KeepAliveModel : PageModel
{
    public IActionResult OnPost()
    {
        // 无需额外逻辑,只要请求到达,Session就会自动刷新
        return new OkResult();
    }
}

方案二:结合Azure AD令牌过期的增强实现

由于是Azure AD单点登录,用户的身份令牌也有过期时间,建议同时考虑Session和令牌的过期时间,取较短的那个作为有效超时:

1. 后端计算有效超时时间

public class HomeModel : PageModel
{
    public int EffectiveTimeoutMs { get; set; }

    public void OnGet()
    {
        // 1. 获取Session超时毫秒数
        var sessionTimeoutMs = (int)HttpContext.Session.IdleTimeout.TotalMilliseconds;

        // 2. 获取Azure AD令牌的过期时间(从exp声明中读取)
        int tokenTimeoutMs = sessionTimeoutMs; // 默认取Session超时
        var expClaim = User.FindFirst("exp");
        if (expClaim != null)
        {
            var tokenExpiry = DateTimeOffset.FromUnixTimeSeconds(long.Parse(expClaim.Value)).UtcDateTime;
            tokenTimeoutMs = (int)(tokenExpiry - DateTime.UtcNow).TotalMilliseconds;
        }

        // 3. 取两者中较短的时间作为有效超时
        EffectiveTimeoutMs = Math.Min(sessionTimeoutMs, tokenTimeoutMs);
    }
}

前端脚本只需将sessionTimeoutMs替换为@Model.EffectiveTimeoutMs即可,其余逻辑与方案一一致。

注意事项

  • 确保Startup.cs中Session配置正确:
    services.AddSession(options =>
    {
        options.IdleTimeout = TimeSpan.FromMinutes(1);
        options.Cookie.HttpOnly = true;
        options.Cookie.IsEssential = true;
    });
    
  • 提示组件可替换为自定义模态框(如Bootstrap Modal),提升用户体验;
  • 若站点存在跨域场景,需确保fetch请求携带凭证(credentials: 'include')。

内容的提问来源于stack exchange,提问作者DonDavid12

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 06:11:07