使用Azure Identity认证的ASP.NET MVC应用如何配置会话超时登出
.NET Framework 4.7.2 经典ASP.NET MVC集成Azure AD实现20分钟无操作自动登出方案
默认配置下会话数小时不超时的核心原因是Azure AD OpenID Connect中间件默认开启UseTokenLifetime = true,会直接使用Azure AD侧返回的令牌有效期(通常1~8小时,由租户配置决定)覆盖本地Cookie认证的超时设置,按以下步骤配置即可实现需求:
第一步:调整OWIN Startup认证配置
打开项目中的Startup.Auth.cs文件,优先配置本地Cookie认证规则,再对齐Azure AD认证参数,核心是禁止Azure AD令牌生命周期覆盖本地会话设置:
public void ConfigureAuth(IAppBuilder app) { app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); // 本地会话Cookie配置,是控制空闲超时的核心 app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = CookieAuthenticationDefaults.AuthenticationType, LoginPath = new PathString("/Account/Login"), // 基础超时时间设为20分钟 ExpireTimeSpan = TimeSpan.FromMinutes(20), // 开启滑动过期:用户每次发起请求自动重置超时计时 SlidingExpiration = true, CookieHttpOnly = true, CookieSecure = CookieSecureOption.Always, Provider = new CookieAuthenticationProvider { OnResponseSignIn = context => { // 强制覆盖认证票据的时间戳,避免Azure AD返回的有效期干扰 context.Properties.IssuedUtc = DateTimeOffset.UtcNow; context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(20); }, OnValidateIdentity = context => { // 跳过匿名请求校验 if (!context.Request.User.Identity.IsAuthenticated) { return Task.FromResult(0); } // 校验最后活跃时间,超过20分钟无请求直接作废会话 var lastActiveTime = context.Properties.IssuedUtc; if (lastActiveTime.HasValue && DateTimeOffset.UtcNow.Subtract(lastActiveTime.Value) > TimeSpan.FromMinutes(20)) { context.RejectIdentity(); context.OwinContext.Authentication.SignOut( CookieAuthenticationDefaults.AuthenticationType, OpenIdConnectAuthenticationDefaults.AuthenticationType); context.Response.Redirect("/Account/TimeoutLogout"); } return Task.FromResult(0); } } }); // Azure AD OpenID Connect配置 app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { ClientId = ConfigurationManager.AppSettings["ida:ClientId"], Authority = $"https://login.microsoftonline.com/{ConfigurationManager.AppSettings["ida:TenantId"]}", RedirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"], PostLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"], // 核心配置:设为false,不使用Azure AD令牌的有效期覆盖本地Cookie超时 UseTokenLifetime = false // 其余原有Azure AD配置保持不变即可 }); }
第二步:对齐Web.config服务端会话配置
在Web.config的<system.web>节点下修改配置,避免IIS默认会话规则和OWIN配置冲突:
<system.web> <!-- 关闭IIS默认Forms认证,完全使用OWIN管道处理认证 --> <authentication mode="None" /> <!-- 服务端Session超时同步设为20分钟,和Cookie规则对齐 --> <sessionState timeout="20" cookieless="false" cookieSecure="Always" /> <!-- 强制Cookie加HttpOnly、SSL标记,避免篡改 --> <httpCookies httpOnlyCookies="true" requireSSL="true" /> </system.web>
第三步:添加前端空闲检测兜底(可选但推荐)
如果用户停留在页面无任何请求操作,服务端无法主动感知空闲状态,可在全局布局页_Layout.cshtml末尾加一段JS检测,20分钟无鼠标、键盘、滚动等操作时主动触发登出:
<script> let idleMinutes = 0; // 监听所有代表用户活跃的操作事件 const activeEvents = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart']; // 每分钟统计一次空闲时长 setInterval(() => { idleMinutes++; if (idleMinutes >= 20) { window.location.href = '/Account/TimeoutLogout'; } }, 60000); // 触发活跃事件时重置空闲计时 activeEvents.forEach(evt => { document.addEventListener(evt, () => idleMinutes = 0, false); }); </script>
第四步:补全超时登出逻辑
在AccountController中添加超时登出接口,同时清除本地Cookie和Azure AD侧的会话状态:
public ActionResult TimeoutLogout() { HttpContext.GetOwinContext().Authentication.SignOut( CookieAuthenticationDefaults.AuthenticationType, OpenIdConnectAuthenticationDefaults.AuthenticationType); // 可跳转至自定义超时提示页,或直接返回首页 return RedirectToAction("Index", "Home", new { timeoutNotify = true }); }
注意:配置完成后务必清除浏览器中存储的站点旧Cookie再测试,否则之前生成的长效Cookie会持续生效,导致误以为配置不生效。
内容的提问来源于stack exchange,提问作者Jashvita
相关产品推荐
相关产品推荐

