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

Vue+Laravel项目实现自动刷新token与用户无操作自动登出咨询

你现有代码的问题是仅在页面初始化时执行一次计时,没有监听用户操作重置计时,也没有覆盖token刷新的逻辑,可按以下方案实现:

1 实现用户无操作3分钟自动登出

逻辑:监听页面内所有用户活跃事件(鼠标点击、移动、键盘输入、滚动、触摸操作),每次事件触发时重置倒计时,倒计时归0后执行登出逻辑,可直接在main.js中添加如下代码:

// 全局计时器变量
let logoutTimer = null
const LOGOUT_DELAY = 3 * 60 * 1000 // 3分钟,单位毫秒

// 重置倒计时函数
const resetLogoutTimer = () => {
  // 先清除已有计时器
  if (logoutTimer) clearTimeout(logoutTimer)
  // 重新开始计时
  logoutTimer = setTimeout(() => {
    // 执行登出逻辑:清除本地token、跳转到登录页
    localStorage.removeItem('token')
    window.location.href = "domain.com/logout"
  }, LOGOUT_DELAY)
}

// 监听用户活跃事件,触发时重置计时器
const userEvents = ['click', 'mousemove', 'keydown', 'scroll', 'touchstart']
userEvents.forEach(event => {
  window.addEventListener(event, resetLogoutTimer, { passive: true })
})

// 页面初始化时启动第一次计时
resetLogoutTimer()

passive: true 是为了优化滚动事件性能,避免页面卡顿。

2 实现自动刷新Token

推荐用响应拦截器触发刷新的方式,比固定定时刷新更节省资源:
逻辑:配置axios响应拦截器,当接口返回401(Token过期)时,先调用refresh接口获取新token,更新本地存储的token后重发之前失败的请求;如果refresh接口也失败,直接触发登出,代码示例:

import axios from 'axios'

// 给axios配置基础域名
axios.defaults.baseURL = 'domain.com'
// 标记是否正在刷新token,避免重复调用refresh接口
let isRefreshing = false
// 存储刷新期间失败的请求队列
let failedQueue = []

// 请求拦截器:给所有请求头加token
axios.interceptors.request.use(config => {
  const token = localStorage.getItem('token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
})

// 响应拦截器:处理token过期逻辑
axios.interceptors.response.use(
  response => response,
  error => {
    const originalRequest = error.config
    // 接口返回401且不是refresh请求本身
    if (error.response.status === 401 && !originalRequest._retry) {
      if (isRefreshing) {
        // 正在刷新的话,把当前请求加入队列,等刷新完成后再执行
        return new Promise(resolve => {
          failedQueue.push(token => {
            originalRequest.headers.Authorization = `Bearer ${token}`
            resolve(axios(originalRequest))
          })
        })
      }

      originalRequest._retry = true
      isRefreshing = true

      return axios.post('/api/refresh')
        .then(res => {
          const newToken = res.data.token
          localStorage.setItem('token', newToken)
          axios.defaults.headers.common.Authorization = `Bearer ${newToken}`
          
          // 刷新成功后执行队列里的所有请求
          failedQueue.forEach(callback => callback(newToken))
          failedQueue = []
          
          return axios(originalRequest)
        })
        .catch(() => {
          // 刷新token失败,直接登出
          localStorage.removeItem('token')
          window.location.href = "domain.com/logout"
          return Promise.reject(error)
        })
        .finally(() => {
          isRefreshing = false
        })
    }
    return Promise.reject(error)
  }
)
注意事项
  • 后端Laravel需要配置好Token刷新逻辑,确保/api/refresh接口可以正常返回新的Token,Token的有效期建议设置为1-2小时,刷新Token的有效期可以设置为7天左右,和前端逻辑匹配
  • 如果需要适配多标签页场景,可以监听storage事件,当其他标签页清除Token时,当前标签页也同步触发登出
  • 若对安全性要求较高,建议将Token存储在HttpOnly Cookie中,避免XSS攻击窃取Token的风险

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 05:18:01