浏览器关闭实现登出(后端清token)

实现浏览器关闭后,后端记录用户登出日志的最佳方式是通过前端发送请求来通知后端进行记录。以下是一种常见的实现方式,重点就是如何区分用户行为是页面刷新还是关闭浏览器。

js 复制代码
// 写在APP.vue
mounted() {  
    window.addEventListener("beforeunload", () => this.beforeunloadHandler())
    window.addEventListener("unload", () => this.unloadHandler())  
},
  
destroyed() {
    window.removeEventListener("beforeunload", () => this.beforeunloadHandler())
    window.removeEventListener("unload", () => this.unloadHandler())
    clearInterval(this.timer)
},

methods:{
     beforeunloadHandler() {
      this.beforeUnloadTime = new Date().getTime()
    },
    unloadHandler() {
      this.gapTime = new Date().getTime() - this.beforeUnloadTime
      if (this.gapTime <= 5) { //判断是窗口关闭还是刷新,小于5代表关闭,否则就是刷新。
        // 这里是关闭浏览器
        logout()
      }
    },
}

但是经测试,发现上面这种浏览器关闭事件并不是一种可靠的方式来捕捉用户的登出操作,后端并非百分百接收到logout请求,经查资料得知,在unload阶段发送的异步请求是不可靠的,有可能被cancel。后面又尝试了fetch,设置了keepalive(即使浏览器关闭,请求照样发送), 但是又发现gapTime<=5的判断条件也存在兼容性问题,不同浏览器的时间差存在差异。此外还存在一些特殊情况:用户可能直接关闭浏览器窗口、断开网络连接或发生其他异常情况,导致浏览器关闭事件无法被触发,因此pass掉上述方案。

后面也尝试了心跳机制(websocket),也存在局限性,pass。

最后想到了一种最简单,最朴实的方式: 开启定时器每秒往localStorage写入当前时间lastRecordTime(new Date().getTime()), 在请求拦截器中给每个接口请求头带上两个时间,最后一次写入时间lastRecordTime和当前时间nowTime, 后端只要把两个时间相减, 超过5s(自定义)就算登出,清掉redis里相应的token。

js 复制代码
// 写在APP.vue
created (){
    // 每秒写入一次时间
    this.timer = setInterval(() => {
    // 这个判断代表登录成功后才开始写入时间
      if(localStorage.getItem('token')) {
        localStorage.setItem('lastRecordTime', new Date().getTime())
      }
    }, 1000)
  }

另外需要注意, 在登录成功的地方要立即写入一次时间, 不然有BUG。

js 复制代码
  // 写在请求拦截器
  const headers = config.headers;
  /** 用于判断用户是否关闭过浏览器,如果关闭则跳转至登录页面,以及及时清理redis中的token */
  if (localStorage.getItem('lastRecordTime')) {
    headers.lastRecordTime = localStorage.getItem('lastRecordTime');
  }
  headers.nowTime = new Date().getTime();

总结一下,目前没发现哪种方式可以提供一种可靠的通信方式去通知后端清除token, 通过两个时间差的方式相对靠谱。

相关推荐
Felicity_Gao2 小时前
uni-app VOD 与 COS 选型、开发笔记
前端·笔记·uni-app
我狸才不是赔钱货4 小时前
前端技术栈全景图:从HTML到现代框架的演进之路
前端·html
百花~4 小时前
前端三剑客之一 HTML~
前端·html
lang201509285 小时前
Spring远程调用与Web服务全解析
java·前端·spring
listhi5207 小时前
利用React Hooks简化状态管理
前端·javascript·react.js
一点一木7 小时前
🚀 2025 年 10 月 GitHub 十大热门项目排行榜 🔥
前端·人工智能·github
华仔啊7 小时前
这个Vue3旋转菜单组件让项目颜值提升200%!支持多种主题,拿来即用
前端·javascript·css
非凡ghost8 小时前
Adobe Lightroom安卓版(手机调色软件)绿色版
前端·windows·adobe·智能手机·软件需求
BestAns8 小时前
Postman 平替?这款轻量接口测试工具,本地运行 + 批量回归超实用!
前端
专注前端30年9 小时前
Webpack进阶玩法全解析(性能优化+高级配置)
前端·webpack·性能优化