fix: redirect expired sessions to login

This commit is contained in:
wren
2026-05-06 18:33:43 +08:00
parent 2d8bab2c91
commit 57c744eb17
2 changed files with 24 additions and 5 deletions
+15 -2
View File
@@ -31,6 +31,17 @@ export function ClientAuthGuard({ isPublicPath, frontendJWT, userInfo }: ClientA
return;
}
// 服务端如果已经拿不到有效 session,就不要再信任本地残留 token。
// 否则页面会出现“模块全空了”,但又没有跳回登录页的假登录状态。
if (!frontendJWT && !userInfo) {
console.warn('⚠️ [Auth Guard] 服务端会话已失效,清理本地登录态并跳转登录页');
localStorage.removeItem('access_token');
localStorage.removeItem('user_info');
const redirectTo = `${location.pathname}${location.search}` || '/';
navigate(`/login?expired=true&redirect=${encodeURIComponent(redirectTo)}`, { replace: true });
return;
}
// 优先用服务端 session 回传的数据同步 localStorage。
// 不能只在本地没有 token 时才回填,否则本地残留旧 token 会导致:
// - SSR 页面可打开(服务端 session 是新的)
@@ -55,14 +66,16 @@ export function ClientAuthGuard({ isPublicPath, frontendJWT, userInfo }: ClientA
console.log('🔒 [Auth Guard] 未认证,重定向到登录页');
// 保存当前路径,登录后可以跳转回来
const redirectTo = location.pathname !== '/login' ? location.pathname : '/';
const redirectTo = location.pathname !== '/login'
? `${location.pathname}${location.search}`
: '/';
// 跳转到登录页,并传递重定向目标
navigate(`/login?redirect=${encodeURIComponent(redirectTo)}`, { replace: true });
} else {
// console.log('✅ [Auth Guard] 已认证,允许访问');
}
}, [isPublicPath, navigate, location.pathname, frontendJWT, userInfo]);
}, [isPublicPath, navigate, location.pathname, location.search, frontendJWT, userInfo]);
// 这个组件不渲染任何内容
return null;
+9 -3
View File
@@ -300,12 +300,18 @@ export async function loader({ request }: LoaderFunctionArgs) {
if (error instanceof Error && error.name === 'AuthenticationError') {
console.warn("⚠️ [Root Loader] Token 过期,重定向到登录页");
// 保存当前路径,登录后可以跳转回来
const redirectTo = pathname !== '/login' ? pathname : '/';
return redirect(`/login?redirect=${encodeURIComponent(redirectTo)}`);
const redirectTo = pathname !== '/login' ? `${pathname}${url.search}` : '/';
return redirect(`/login?expired=true&redirect=${encodeURIComponent(redirectTo)}`);
}
console.warn("⚠️ [Root Loader] 获取用户会话失败:", error);
// 保持默认值 'common'
// 非公共页只要服务端会话初始化失败,就直接回登录页,
// 避免落入“角色=common + 菜单全空”的假登录状态。
if (!isPublicPath) {
const redirectTo = pathname !== '/login' ? `${pathname}${url.search}` : '/';
return redirect(`/login?expired=true&redirect=${encodeURIComponent(redirectTo)}`);
}
}
// 注意:认证检查和重定向已在 getUserSession() 中统一处理