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

如何检测用户在开发者控制台手动刷新/移除Access Token或HTTP-only Cookie?

解决方案:MERN栈下检测页面刷新、Token/Cookie手动移除并自动登出

一、检测页面刷新行为

页面刷新时浏览器会触发beforeunload事件,同时React组件会先卸载再重新挂载,可通过以下方式检测:

  1. beforeunload事件 + 存储标记
    在React全局布局或根组件中添加:
useEffect(() => {
  const handleBeforeUnload = (e) => {
    // 标记用户即将刷新/关闭页面
    sessionStorage.setItem('isRefreshing', 'true');
    e.returnValue = ''; // 部分浏览器需要这个参数触发默认提示
  };

  window.addEventListener('beforeunload', handleBeforeUnload);

  return () => {
    window.removeEventListener('beforeunload', handleBeforeUnload);
    // 组件卸载时清除标记(关闭标签页会触发,刷新时会先清除再重新加载)
    sessionStorage.removeItem('isRefreshing');
  };
}, []);

页面加载完成后,若sessionStorage.getItem('isRefreshing')存在,即可判定为刷新操作,执行重新验证或登出逻辑。

  1. 组件卸载时的状态判断
    结合上述标记,在全局Auth组件的卸载钩子中处理:
useEffect(() => {
  return () => {
    if (sessionStorage.getItem('isRefreshing')) {
      // 触发刷新后的身份验证逻辑
      checkAuthStatus();
    }
  };
}, []);

二、检测手动移除Access Token(非HTTP-only)

如果Access Token存在localStorage或sessionStorage中,可通过两种方式检测:

  1. storage事件监听(跨标签页场景)
    当其他标签页删除Token时,当前页会触发storage事件:
useEffect(() => {
  const handleStorageChange = (e) => {
    if (e.key === 'accessToken' && e.newValue === null) {
      // Token被手动删除,触发登出
      logout();
    }
  };

  window.addEventListener('storage', handleStorageChange);
  return () => window.removeEventListener('storage', handleStorageChange);
}, []);
  1. 定时轮询 + 请求前检查(当前标签页场景)
    当前标签页手动删除Token时storage事件不会触发,需主动检查:
  • 定时轮询(示例间隔3秒):
useEffect(() => {
  const interval = setInterval(() => {
    const token = localStorage.getItem('accessToken');
    // 若之前已认证但Token消失,触发登出
    if (!token && isAuthenticated()) {
      logout();
    }
  }, 3000);

  return () => clearInterval(interval);
}, []);
  • Axios请求拦截器前置检查:
axios.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('accessToken');
    if (!token && isAuthenticated()) {
      logout();
      return Promise.reject(new Error('Token removed manually'));
    }
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

三、检测HTTP-only Cookie删除(核心实现)

由于JS无法直接读取或操作HTTP-only Cookie,前端无法直接检测其是否被删除,只能通过后端验证间接判断:

实现思路

  1. 后端提供轻量验证接口(如GET /api/auth/verify),检查请求中的HTTP-only Cookie(存储Refresh Token)是否有效;
  2. 前端定时发起该请求,或在路由跳转、关键操作前触发验证;
  3. 若后端返回401(Cookie无效/不存在),前端立即执行登出逻辑。

代码示例

后端(Node.js/Express)

// 验证Cookie中的Refresh Token
app.get('/api/auth/verify', async (req, res) => {
  try {
    const refreshToken = req.cookies.refreshToken;
    if (!refreshToken) {
      return res.status(401).json({ message: 'Cookie missing' });
    }
    // 验证Refresh Token有效性(JWT校验或数据库查询)
    const user = await verifyRefreshToken(refreshToken);
    res.status(200).json({ user: { id: user._id, email: user.email } });
  } catch (err) {
    res.status(401).json({ message: 'Invalid or missing cookie' });
  }
});

前端(React + Axios)

useEffect(() => {
  const verifyCookieInterval = setInterval(async () => {
    try {
      // 携带Cookie请求验证接口
      await axios.get('/api/auth/verify', { withCredentials: true });
    } catch (err) {
      if (err.response.status === 401) {
        // Cookie被删除/无效,触发登出
        logout();
      }
    }
  }, 5000); // 每5秒验证一次,可按需调整间隔

  return () => clearInterval(verifyCookieInterval);
}, []);

四、Axios拦截器失效的常见修复方案

如果你的拦截器未生效,大概率是以下问题:

  1. 未使用统一Axios实例:确保所有请求都使用添加了拦截器的实例,而非每次新建axios.create():
// 创建全局Axios实例
const api = axios.create({ baseURL: '/api', withCredentials: true });
// 给实例添加拦截器
api.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response.status === 401) {
      logout();
    }
    return Promise.reject(error);
  }
);
// 所有请求使用该实例
export default api;
  1. 未开启withCredentials:若请求需要携带HTTP-only Cookie,必须在Axios配置中设置withCredentials: true,否则Cookie不会被发送到后端;
  2. 拦截器逻辑错误:检查是否正确处理了401响应,或请求拦截器中是否遗漏了Token检查逻辑。

总结

  • 页面刷新:通过beforeunload事件+存储标记结合检测;
  • Access Token手动移除:storage事件(跨标签页)+ 定时轮询/请求前检查(当前页);
  • HTTP-only Cookie删除:通过后端验证接口定时检测,收到401后触发登出;
  • Axios拦截器失效:检查实例一致性、withCredentials配置及逻辑正确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 21:35:20