ASP.NET Core MVC 2.2 如何阻止用户登出后点击浏览器返回按钮?
登出后禁止浏览器回退访问已认证页面解决方案
原代码失效核心原因
你使用的window.history.forward(1)未生效主要有三点原因:
- 浏览器自带**往返缓存(bfcache)**机制,点击回退按钮时会直接读取本地缓存的页面快照,不会重新执行页面内的普通JS逻辑
- 没有配合服务端缓存禁用策略,就算前端逻辑生效,浏览器仍可直接加载缓存的历史页面无需请求服务端
- 代码执行时机错误,仅单独调用该方法无法覆盖回退场景的触发逻辑
具体实现方案
第一步:服务端禁用敏感页面缓存(核心必须配置)
ASP.NET Core 2.2中可以通过自定义过滤器全局禁用所有需要登录认证页面的缓存,确保浏览器每次访问这些页面都必须向服务端发起请求校验登录状态:
- 新建无缓存过滤器
public class NoCacheAttribute : ActionFilterAttribute { public override void OnResultExecuting(ResultExecutingContext context) { context.HttpContext.Response.Headers["Cache-Control"] = "no-cache, no-store, must-revalidate"; context.HttpContext.Response.Headers["Pragma"] = "no-cache"; context.HttpContext.Response.Headers["Expires"] = "0"; base.OnResultExecuting(context); } }
- 注册过滤器,两种方式二选一即可:
- 方式1:仅给需要登录的Controller/Action添加
[NoCache]属性 - 方式2:全局注册,所有页面生效,在
Startup.cs的ConfigureServices方法中添加配置:
services.AddMvc(options => { options.Filters.Add(typeof(NoCacheAttribute)); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2); - 方式1:仅给需要登录的Controller/Action添加
- 确保登出逻辑中正确清除认证凭证:
public async Task<IActionResult> Logout() { await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return RedirectToAction("Login"); }
第二步:前端补充适配逻辑
配合服务端逻辑,添加JS覆盖bfcache场景的校验:
- 在所有需要认证的页面添加如下JS,监听页面从缓存加载的事件:
window.addEventListener('pageshow', function(event) { // event.persisted为true代表页面是从bfcache加载的 if (event.persisted) { // 发起轻量请求校验当前登录状态,携带cookie fetch('/Account/CheckLoginStatus', { credentials: 'include' }) .then(res => { // 未登录则跳转到登录页 if (res.status === 401) { window.location.href = '/Account/Login'; } }); } });
- 在登出成功的回调中新增历史记录替换逻辑,避免回退到之前的认证页面:
// 登出接口调用成功后执行 history.replaceState(null, null, '/Account/Login'); window.location.href = '/Account/Login';
内容的提问来源于stack exchange,提问作者ahmed assiri
相关产品推荐
相关产品推荐

