Skip to content

Commit 22d7334

Browse files
committed
feat: 增强 token 刷新逻辑,添加用户信息恢复功能;优化过期检查处理
1 parent b0351f7 commit 22d7334

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

frontend/components/Header.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Link from 'next/link';
66
import ScrollHeader from './ScrollHeader';
77
import ThemeToggle from './ThemeToggle';
88
import type { User } from '@/types/api';
9-
import { isTokenExpired, clearAuth, startTokenExpiryWatch, stopTokenExpiryWatch, logout } from '@/lib/auth';
9+
import { isTokenExpired, startTokenExpiryWatch, stopTokenExpiryWatch, logout } from '@/lib/auth';
1010

1111
// 定义导航菜单项
1212
const navItems = [

frontend/lib/auth.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,26 @@ async function doRefreshToken(): Promise<string | null> {
126126
const data = await response.json();
127127
if (data.token) {
128128
localStorage.setItem('token', data.token);
129+
130+
// 如果 user 信息丢失,从 token payload 恢复基本信息
131+
if (!localStorage.getItem('user')) {
132+
const payload = parseJwtPayload(data.token);
133+
if (payload && payload.sub) {
134+
const basicUser = {
135+
id: payload.sub,
136+
username: (payload as { username?: string }).username || '',
137+
role: (payload as { role?: string }).role || 'user',
138+
email: '',
139+
display_name: null,
140+
avatar_url: null,
141+
bio: null,
142+
created_at: '',
143+
updated_at: '',
144+
};
145+
localStorage.setItem('user', JSON.stringify(basicUser));
146+
}
147+
}
148+
129149
// 触发 storage 事件
130150
window.dispatchEvent(new StorageEvent('storage', { key: 'token' }));
131151
return data.token;
@@ -184,19 +204,29 @@ function scheduleNextCheck(): void {
184204
const timeUntilExpiry = exp - now;
185205

186206
if (timeUntilExpiry <= 0) {
187-
// 已过期,立即触发
188-
authCheckCallback?.();
207+
// 已过期,尝试刷新
208+
tryRefreshToken().then((newToken) => {
209+
if (!newToken) {
210+
clearAuth();
211+
}
212+
authCheckCallback?.();
213+
});
189214
return;
190215
}
191216

192217
// 设置定时器,在过期时触发检查
193218
// 最多等待 60 秒(避免 setTimeout 溢出问题,也保证定期检查)
194219
const delay = Math.min(timeUntilExpiry, 60) * 1000;
195220

196-
checkTimer = setTimeout(() => {
221+
checkTimer = setTimeout(async () => {
197222
const currentToken = localStorage.getItem('token');
198223
if (currentToken && isTokenExpired(currentToken, 0)) {
199-
clearAuth();
224+
// 尝试刷新而不是直接清除
225+
const newToken = await tryRefreshToken();
226+
if (!newToken) {
227+
// 刷新失败才清除
228+
clearAuth();
229+
}
200230
authCheckCallback?.();
201231
} else {
202232
// 还没过期,安排下一次检查

0 commit comments

Comments
 (0)