浏览器关闭实现登出(后端清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, 通过两个时间差的方式相对靠谱。

相关推荐
小小小小宇1 小时前
虚拟列表兼容老DOM操作
前端
悦悦子a啊1 小时前
Python之--基本知识
开发语言·前端·python
安全系统学习2 小时前
系统安全之大模型案例分析
前端·安全·web安全·网络安全·xss
涛哥码咖3 小时前
chrome安装AXURE插件后无效
前端·chrome·axure
OEC小胖胖3 小时前
告别 undefined is not a function:TypeScript 前端开发优势与实践指南
前端·javascript·typescript·web
行云&流水3 小时前
Vue3 Lifecycle Hooks
前端·javascript·vue.js
Sally璐璐3 小时前
零基础学HTML和CSS:网页设计入门
前端·css
老虎06273 小时前
JavaWeb(苍穹外卖)--学习笔记04(前端:HTML,CSS,JavaScript)
前端·javascript·css·笔记·学习·html
灿灿121384 小时前
CSS 文字浮雕效果:巧用 text-shadow 实现 3D 立体文字
前端·css
烛阴4 小时前
Babel 完全上手指南:从零开始解锁现代 JavaScript 开发的超能力!
前端·javascript