React中基于用户活跃状态的Token刷新与注销处理
实现基于用户活跃状态的Token刷新与清除逻辑
以下是修改后的完整代码,完全满足「仅用户活跃时每小时刷新Token,无活跃则清除Token」的需求:
import { useState, useEffect, useCallback } from 'react'; import useAuthStore from './path-to-your-auth-store'; // 替换为你的状态存储路径 import AuthenticationService from './path-to-authentication-service'; // 替换为你的认证服务路径 import CookieService from './path-to-cookie-service'; // 替换为你的Cookie工具路径 const App = () => { const [lastActiveTime, setLastActiveTime] = useState(Date.now()); const [refreshTimerId, setRefreshTimerId] = useState(null); const [inactivityTimerId, setInactivityTimerId] = useState(null); // 把原回调式的refresh接口封装为Promise,简化异步逻辑 const refreshTokenPromise = useCallback(() => { return new Promise((resolve, reject) => { AuthenticationService.refresh(null, resolve, reject); }); }, []); // 核心Token刷新逻辑 const refreshToken = useCallback(async () => { try { const { isLoggedIn } = useAuthStore.getState(); if (isLoggedIn) { const response = await refreshTokenPromise(); CookieService.set(activeAccount, response.data); } // 只有用户1小时内有活跃记录,才设置下一次刷新 const now = Date.now(); if (now - lastActiveTime < 1000 * 60 * 60) { const newTimerId = setTimeout(refreshToken, 1000 * 60 * 60); setRefreshTimerId(newTimerId); } else { setRefreshTimerId(null); } } catch (error) { console.error('Token刷新失败:', error); setRefreshTimerId(null); } }, [lastActiveTime, refreshTokenPromise]); // 启动刷新定时器 const startRefreshInterval = useCallback(() => { const timerId = setTimeout(refreshToken, 1000 * 60 * 60); setRefreshTimerId(timerId); }, [refreshToken]); // 用户活跃事件处理:更新活跃时间、重置不活跃检测 const handleUserActivity = useCallback(() => { setLastActiveTime(Date.now()); // 清除之前的不活跃检测定时器 if (inactivityTimerId) { clearTimeout(inactivityTimerId); } // 设置新的不活跃检测:1小时无操作则清除Token const newInactivityTimer = setTimeout(() => { const { isLoggedIn, setIsLoggedIn } = useAuthStore.getState(); if (isLoggedIn) { CookieService.remove(activeAccount); setIsLoggedIn(false); // 同步更新全局登录状态 } // 终止刷新定时器 if (refreshTimerId) { clearTimeout(refreshTimerId); setRefreshTimerId(null); } }, 1000 * 60 * 60); setInactivityTimerId(newInactivityTimer); // 若未启动刷新定时器,立即启动 if (!refreshTimerId) { startRefreshInterval(); } }, [inactivityTimerId, refreshTimerId, startRefreshInterval]); useEffect(() => { const { isLoggedIn } = useAuthStore.getState(); // 监听全局鼠标、键盘事件,捕获用户活跃行为 window.addEventListener('mousemove', handleUserActivity); window.addEventListener('keydown', handleUserActivity); // 初始化时:若已登录,启动不活跃检测和刷新定时器 if (isLoggedIn) { const initialInactivityTimer = setTimeout(() => { const { setIsLoggedIn } = useAuthStore.getState(); CookieService.remove(activeAccount); setIsLoggedIn(false); }, 1000 * 60 * 60); setInactivityTimerId(initialInactivityTimer); startRefreshInterval(); } // 组件卸载时清理所有定时器和事件监听 return () => { window.removeEventListener('mousemove', handleUserActivity); window.removeEventListener('keydown', handleUserActivity); if (refreshTimerId) clearTimeout(refreshTimerId); if (inactivityTimerId) clearTimeout(inactivityTimerId); }; }, [handleUserActivity, isLoggedIn, startRefreshInterval, refreshTimerId, inactivityTimerId]); return null; }; export default App;
关键逻辑说明
- 用户活跃跟踪:通过监听全局
mousemove和keydown事件,实时更新用户最后活跃时间,每次活跃都会重置不活跃检测定时器 - Token刷新控制:仅当用户1小时内有活跃记录时,才会维持刷新定时器;若用户超过1小时无操作,刷新定时器自动终止,不再调用刷新API
- 不活跃Token清除:用户连续1小时无操作时,自动清除Token并同步更新全局登录状态,同时终止所有相关定时器
- API适配:将原回调式的刷新接口封装为Promise,用
async/await简化异步代码,提升可读性和可维护性
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

