生产管理系统 - 每5分钟提交一次刷新token的请求
This commit is contained in:
@@ -130,6 +130,7 @@ export function LoginForm({ onRegisterClick }: LoginFormProps) {
|
||||
createdAt: response.data.created_at || new Date().toISOString(),
|
||||
// 重要:存储token到用户对象中
|
||||
token: response.data.access_token || response.data.token || null,
|
||||
refreshToken:response.data.refresh_token || ''
|
||||
};
|
||||
|
||||
// 打印登录成功日志
|
||||
@@ -138,7 +139,7 @@ export function LoginForm({ onRegisterClick }: LoginFormProps) {
|
||||
apiResponse: response.data,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
debugger
|
||||
// 验证token是否正确存储
|
||||
if (userData.token) {
|
||||
console.log('🔑 Token已存储:', userData.token.substring(0, 20) + '...');
|
||||
@@ -148,11 +149,8 @@ export function LoginForm({ onRegisterClick }: LoginFormProps) {
|
||||
|
||||
login(userData);
|
||||
toast.success('登录成功!正在跳转...');
|
||||
|
||||
// 跳转到个人中心页面
|
||||
setTimeout(() => {
|
||||
window.location.href = '/central-config/personal-center/personal-info';
|
||||
}, 1000);
|
||||
} else {
|
||||
dispatch({ type: 'SET_ERROR', payload: '登录失败,请检查用户名和密码' });
|
||||
toast.error('登录失败,请检查用户名和密码');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import React, { createContext, useContext, useState, ReactNode } from 'react';
|
||||
import { getCurrentUserInfoApiV1AuthMeGet } from '@/lib/api/sdk.gen';
|
||||
import React, { createContext, useContext, useState, ReactNode, useRef } from 'react';
|
||||
import { getCurrentUserInfoApiV1AuthMeGet, refreshTokenApiV1AuthRefreshPost } from '@/lib/api/sdk.gen';
|
||||
|
||||
// Cookie 操作工具
|
||||
const setTokenCookie = (token: string) => {
|
||||
@@ -46,6 +46,7 @@ interface AuthProviderProps {
|
||||
export function AuthProvider({ children }: AuthProviderProps) {
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const refreshTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
const login = (userData: User) => {
|
||||
setUser(userData);
|
||||
@@ -58,6 +59,9 @@ export function AuthProvider({ children }: AuthProviderProps) {
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
|
||||
// 登录成功后,启动 token 自动刷新定时器
|
||||
startTokenRefresh();
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
@@ -66,12 +70,127 @@ export function AuthProvider({ children }: AuthProviderProps) {
|
||||
removeTokenCookie(); // 清除 cookie
|
||||
setLoading(false);
|
||||
|
||||
// 清除定时器
|
||||
if (refreshTimerRef.current) {
|
||||
clearInterval(refreshTimerRef.current);
|
||||
refreshTimerRef.current = null;
|
||||
}
|
||||
|
||||
// 跳转到登录页
|
||||
if (typeof window !== 'undefined') {
|
||||
window.location.href = '/login';
|
||||
}
|
||||
};
|
||||
|
||||
// 刷新 token 的函数
|
||||
const refreshAccessToken = async () => {
|
||||
try {
|
||||
const storedUser = localStorage.getItem('user');
|
||||
if (!storedUser) {
|
||||
console.warn('⚠️ 未找到用户信息,无法刷新 token');
|
||||
return;
|
||||
}
|
||||
|
||||
const userData = JSON.parse(storedUser);
|
||||
if (!userData.token) {
|
||||
console.warn('⚠️ 用户信息中没有 token,无法刷新');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🔄 开始刷新 token...');
|
||||
console.log('📝 当前 token (前20字符):', userData.token.substring(0, 20) + '...');
|
||||
|
||||
const response = await refreshTokenApiV1AuthRefreshPost({
|
||||
headers: {
|
||||
'Authorization': `Bearer ${userData.refreshToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
console.log('📨 刷新接口响应:', response);
|
||||
|
||||
// 检查响应数据结构
|
||||
if (response.data) {
|
||||
console.log('📋 响应数据结构:', JSON.stringify(response.data, null, 2));
|
||||
|
||||
// 尝试多种可能的 token 字段名
|
||||
const newToken = response.data.access_token || ""
|
||||
const refreshToken = response.data.refresh_token || ""
|
||||
|
||||
if (newToken) {
|
||||
// 更新用户信息中的 token
|
||||
const updatedUserData = {
|
||||
...userData,
|
||||
token: newToken,
|
||||
refreshToken:refreshToken,
|
||||
// 如果有其他 token 相关字段也一并更新
|
||||
};
|
||||
|
||||
// 更新 localStorage
|
||||
localStorage.setItem('user', JSON.stringify(updatedUserData));
|
||||
|
||||
// 更新状态
|
||||
setUser(updatedUserData);
|
||||
|
||||
// 更新 cookie
|
||||
setTokenCookie(newToken);
|
||||
|
||||
console.log('✅ Token 刷新成功');
|
||||
console.log('🔑 新 token (前20字符):', newToken.substring(0, 20) + '...');
|
||||
} else {
|
||||
console.error('❌ Token 刷新失败:响应中未找到 token 字段');
|
||||
console.log('🔍 可用字段:', Object.keys(response.data));
|
||||
// 先不登出,记录错误,让用户继续使用当前 token
|
||||
console.log('⚠️ 暂不执行登出,继续使用当前 token');
|
||||
}
|
||||
} else {
|
||||
console.error('❌ Token 刷新失败:响应数据为空');
|
||||
console.log('📊 完整响应:', response);
|
||||
// 先不登出,可能是接口问题
|
||||
console.log('⚠️ 暂不执行登出,可能是接口问题');
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('❌ Token 刷新失败:', error);
|
||||
console.log('📝 错误详情:', {
|
||||
message: error.message,
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
data: error.response?.data
|
||||
});
|
||||
|
||||
// 根据错误类型决定是否登出
|
||||
if (error.response?.status === 401) {
|
||||
console.log('🔒 Token 已过期,执行登出');
|
||||
logout();
|
||||
} else {
|
||||
console.log('⚠️ 网络或服务器错误,暂不执行登出');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 启动定时刷新 token
|
||||
const startTokenRefresh = () => {
|
||||
// 清除之前的定时器
|
||||
if (refreshTimerRef.current) {
|
||||
clearInterval(refreshTimerRef.current);
|
||||
}
|
||||
|
||||
// 每 1 分钟刷新一次 token
|
||||
refreshTimerRef.current = setInterval(() => {
|
||||
refreshAccessToken();
|
||||
}, 5 * 60 * 1000); // 60 秒 = 1 分钟
|
||||
|
||||
console.log('🕐 Token 自动刷新定时器已启动(每5分钟)');
|
||||
};
|
||||
|
||||
// 停止定时刷新 token
|
||||
const stopTokenRefresh = () => {
|
||||
if (refreshTimerRef.current) {
|
||||
clearInterval(refreshTimerRef.current);
|
||||
refreshTimerRef.current = null;
|
||||
console.log('⏹️ Token 自动刷新定时器已停止');
|
||||
}
|
||||
};
|
||||
|
||||
// 验证当前用户信息
|
||||
const validateUser = async () => {
|
||||
try {
|
||||
@@ -92,11 +211,15 @@ export function AuthProvider({ children }: AuthProviderProps) {
|
||||
|
||||
if (response.data) {
|
||||
// 更新用户信息(可能包含最新的权限、角色等)
|
||||
setUser({
|
||||
const updatedUserData = {
|
||||
...userData,
|
||||
...response.data, // 合并最新的用户信息
|
||||
});
|
||||
};
|
||||
setUser(updatedUserData);
|
||||
console.log('✅ 用户验证成功,最新用户信息:', response.data);
|
||||
|
||||
// 验证成功后,启动 token 自动刷新定时器
|
||||
startTokenRefresh();
|
||||
} else {
|
||||
// Token无效,清除用户信息
|
||||
console.warn('⚠️ Token验证失败,清除用户信息');
|
||||
@@ -133,6 +256,14 @@ export function AuthProvider({ children }: AuthProviderProps) {
|
||||
validateUser();
|
||||
}, []);
|
||||
|
||||
// 清理定时器
|
||||
React.useEffect(() => {
|
||||
return () => {
|
||||
// 组件卸载时清理定时器
|
||||
stopTokenRefresh();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const value: AuthContextType = {
|
||||
user,
|
||||
login,
|
||||
|
||||
Reference in New Issue
Block a user