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

React结合React Router:JWT令牌过期后如何自动登出用户?

结合React Router实现JWT会话自动过期登出的最佳方案

1. 解析并存储JWT过期时间

后端返回JWT后,除了把token存入localStorage,还要解析出payload里的exp字段(秒级时间戳),转成毫秒级后存储到期时间。这样不用每次都解码token判断过期状态。

// 解码JWT payload的工具函数
const decodeJwt = (token) => {
  const base64Url = token.split('.')[1];
  const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
  return JSON.parse(window.atob(base64));
};

// 登录成功后存储token和过期时间
const handleLogin = async () => {
  const response = await fetch('/api/login', { method: 'POST', body: ... });
  const { token } = await response.json();
  const { exp } = decodeJwt(token);
  // 转成毫秒级时间戳,方便和Date.now()比较
  const expiresAt = exp * 1000;
  
  localStorage.setItem('authToken', token);
  localStorage.setItem('expiresAt', expiresAt.toString());
};

2. 全局管理登录状态与自动登出逻辑

用React Context封装登录状态和登出方法,在全局监听会话过期,同时处理页面刷新、标签页切换的场景。

import { createContext, useContext, useEffect, useState } from 'react';

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  let logoutTimer;

  // 初始化时检查登录状态
  useEffect(() => {
    const token = localStorage.getItem('authToken');
    const expiresAt = localStorage.getItem('expiresAt');
    
    if (token && expiresAt) {
      const currentTime = Date.now();
      if (currentTime < expiresAt) {
        setIsAuthenticated(true);
        // 设置自动登出计时器
        const timeRemaining = expiresAt - currentTime;
        logoutTimer = setTimeout(handleLogout, timeRemaining);
      } else {
        handleLogout();
      }
    }
    // 组件卸载时清除计时器,避免内存泄漏
    return () => clearTimeout(logoutTimer);
  }, []);

  // 监听页面可见性,切换回页面时检查是否过期
  useEffect(() => {
    const handleVisibilityChange = () => {
      if (document.visibilityState === 'visible') {
        const expiresAt = localStorage.getItem('expiresAt');
        if (expiresAt && Date.now() >= expiresAt) {
          handleLogout();
        }
      }
    };
    document.addEventListener('visibilitychange', handleVisibilityChange);
    return () => document.removeEventListener('visibilitychange', handleVisibilityChange);
  }, []);

  const handleLogout = () => {
    localStorage.removeItem('authToken');
    localStorage.removeItem('expiresAt');
    setIsAuthenticated(false);
    clearTimeout(logoutTimer);
    // 跳转登录页
    window.location.href = '/login';
  };

  return (
    <AuthContext.Provider value={{ isAuthenticated, handleLogout }}>
      {children}
    </AuthContext.Provider>
  );
};

// 自定义Hook快速获取AuthContext
export const useAuth = () => useContext(AuthContext);

3. 封装React Router路由守卫

创建ProtectedRoute组件,拦截需要登录权限的路由,校验token有效性,无效则重定向到登录页。

import { Navigate, Outlet } from 'react-router-dom';
import { useAuth } from './AuthContext';

export const ProtectedRoute = () => {
  const { isAuthenticated } = useAuth();
  const token = localStorage.getItem('authToken');
  const expiresAt = localStorage.getItem('expiresAt');
  
  // 双重校验:全局状态+localStorage过期时间
  const isTokenValid = token && expiresAt && Date.now() < expiresAt;

  if (!isAuthenticated || !isTokenValid) {
    return <Navigate to="/login" replace />;
  }

  return <Outlet />;
};

在路由配置中使用:

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

function App() {
  return (
    <AuthProvider>
      <Routes>
        <Route path="/login" element={<Login />} />
        {/* 需登录的路由统一放在ProtectedRoute下 */}
        <Route element={<ProtectedRoute />}>
          <Route path="/dashboard" element={<Dashboard />} />
          <Route path="/profile" element={<Profile />} />
        </Route>
        <Route path="/" element={<Navigate to="/dashboard" replace />} />
      </Routes>
    </AuthProvider>
  );
}

4. 关键注意事项

  • 后端校验优先:前端自动登出仅为体验优化,所有接口请求时后端必须严格校验JWT有效性,防止前端篡改过期时间绕过校验。
  • 异常场景处理:若接口返回401(token失效),需立即触发登出逻辑,覆盖前端校验遗漏的情况。
  • 内存泄漏防范:组件卸载、登出时必须清除setTimeout计时器,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 16:12:32