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

React结合状态管理库时,何时检查JWT令牌过期?

React中JWT令牌过期的正确处理方案

针对你遇到的问题,结合React生态的实践,推荐用全局请求拦截+路由守卫+定时辅助检查的组合方案,完美覆盖你提到的两个方案的缺陷:

1. 全局请求拦截处理401(优化方案2)

服务器返回的401是令牌失效的权威判断,不管用axios、fetch还是其他请求库,都可以封装统一的请求层,把401处理逻辑抽离出来,避免依赖单个请求库:

用axios的示例

import axios from 'axios';
import store from './store'; // 你的状态管理store

const api = axios.create({ baseURL: '/api' });

// 响应拦截器
api.interceptors.response.use(
  res => res,
  err => {
    if (err.response?.status === 401) {
      // 清除状态里的token
      store.dispatch({ type: 'auth/clearToken' });
      // 跳转登录页,带上当前路径方便登录后返回
      window.location.href = `/login?redirect=${encodeURIComponent(window.location.pathname)}`;
    }
    return Promise.reject(err);
  }
);

export default api;

用fetch的示例

如果项目用原生fetch,同样可以封装:

import store from './store';

async function authFetch(url, options = {}) {
  const token = store.getState().auth.token;
  const headers = {
    ...options.headers,
    Authorization: token ? `Bearer ${token}` : ''
  };

  const res = await fetch(url, { ...options, headers });
  
  if (res.status === 401) {
    store.dispatch({ type: 'auth/clearToken' });
    window.location.href = `/login?redirect=${encodeURIComponent(window.location.pathname)}`;
  }

  return res;
}

export default authFetch;

所有接口请求都用这个封装后的方法,就能统一处理401,不用每个请求都写判断。

2. 路由守卫+定时检查(优化方案1)

路由监听的问题是用户停在同一页面时没触发,所以改用路由守卫控制页面访问权限,再加定时检查覆盖停留页面的场景:

路由守卫组件(React Router v6+)

import { Navigate, useLocation } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';

export const RequireAuth = ({ children }) => {
  const token = useSelector(state => state.auth.token);
  const location = useLocation();
  const dispatch = useDispatch();

  // 解析JWT payload,检查是否过期
  const isTokenValid = () => {
    if (!token) return false;
    try {
      const payload = JSON.parse(atob(token.split('.')[1]));
      // 这里可以加个缓冲时间,比如提前5分钟判定为即将过期
      return payload.exp * 1000 > Date.now();
    } catch (e) {
      return false;
    }
  };

  if (!isTokenValid()) {
    dispatch({ type: 'auth/clearToken' });
    // 跳转登录,携带当前页面路由
    return <Navigate to="/login" state={{ from: location }} replace />;
  }

  return children;
};

然后在路由配置里用它保护需要登录的页面:

import { Routes, Route } from 'react-router-dom';
import RequireAuth from './RequireAuth';
import Dashboard from './Dashboard';
import Login from './Login';

function App() {
  return (
    <Routes>
      <Route path="/login" element={<Login />} />
      <Route path="/dashboard" element={
        <RequireAuth>
          <Dashboard />
        </RequireAuth>
      } />
      {/* 其他需要登录的路由同理 */}
    </Routes>
  );
}

定时检查当前页面的token

在全局组件(比如App.js)里加一个定时任务,定期检查token状态,覆盖用户长时间停留在同一页面的场景:

import { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';

function App() {
  const token = useSelector(state => state.auth.token);
  const dispatch = useDispatch();

  useEffect(() => {
    let timeoutId;
    if (token) {
      try {
        const payload = JSON.parse(atob(token.split('.')[1]));
        // 计算距离过期的时间,提前1分钟触发检查
        const timeToCheck = payload.exp * 1000 - Date.now() - 60000;
        
        if (timeToCheck > 0) {
          timeoutId = setTimeout(() => {
            // 再次确认token是否有效
            const stillValid = payload.exp * 1000 > Date.now();
            if (!stillValid) {
              dispatch({ type: 'auth/clearToken' });
              window.location.href = '/login';
            }
          }, timeToCheck);
        } else {
          // 已经过期,直接处理
          dispatch({ type: 'auth/clearToken' });
          window.location.href = '/login';
        }
      } catch (e) {
        // 解析失败,直接清token跳转
        dispatch({ type: 'auth/clearToken' });
        window.location.href = '/login';
      }
    }

    return () => clearTimeout(timeoutId);
  }, [token, dispatch]);

  // ...路由渲染
}

注意:定时检查只是辅助,因为JWT的过期时间是客户端解析的,服务器可能因为其他原因(比如token被吊销)返回401,所以最终还是要以服务器的响应为准。

3. 最佳实践总结

  • 核心逻辑依赖服务器401响应:这是最准确的判断,覆盖所有token失效场景(过期、吊销等)。
  • 路由守卫控制页面访问:处理用户跳转页面时的权限检查,避免未授权访问。
  • 定时检查优化用户体验:在用户停留页面时提前处理过期,不用等到用户触发请求才跳转。

如果项目有刷新token机制,还可以在401时尝试用刷新token获取新的access token,失败再跳转登录,进一步提升用户体验。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 17:30:47