From 8f550adbb18832f64de5550fff6c7971b632ec88 Mon Sep 17 00:00:00 2001 From: commilitia Date: Tue, 16 Jun 2026 00:19:13 +0800 Subject: [PATCH] =?UTF-8?q?web=EF=BC=9AOAuth=20=E5=9B=9E=E8=B0=83=E6=88=90?= =?UTF-8?q?=E5=8A=9F=E5=90=8E=E6=95=B4=E9=A1=B5=E8=B7=B3=E8=BD=AC=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=20Safari=20=E7=99=BB=E5=BD=95=E5=90=8E=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E5=8A=A0=E8=BD=BD=E5=8D=A1=E6=AD=BB=20~2min?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现象:Safari/PWA 从 Casdoor 回跳登录后,setup.js(路由 chunk)与用户头像约 2 分钟拿不到连接(连接号显示「-」),手动刷新即恢复;Chrome 正常。排查确认非 h3、非 service worker、非 SSE(/setup 时 startHub 被 !selfDeviceName 守卫拦下),服务端 curl 秒回。 根因:oauth.callback 登录成功后做的是路由软导航 navigate({to:"/"}),复用了 OAuth 流程遗留的 HTTP 连接,这些连接在 Safari 下会卡死后续同源/跨源资源请求约 2 分钟。整页重载能拿到全新连接(印证:手动刷新即好),故改 navigate 为 window.location.replace("/")。auth 已在 sessionStorage,同标签刷新存活;replace 不入历史,避免后退重触已消费的 code。 顺带移除因此 unused 的 useNavigate import。 --- web/src/routes/oauth.callback.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/web/src/routes/oauth.callback.tsx b/web/src/routes/oauth.callback.tsx index 218b596..1bdf078 100644 --- a/web/src/routes/oauth.callback.tsx +++ b/web/src/routes/oauth.callback.tsx @@ -1,5 +1,5 @@ import { Loader } from "@mantine/core"; -import { createFileRoute, useNavigate } from "@tanstack/react-router"; +import { createFileRoute } from "@tanstack/react-router"; import { AlertTriangle } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { completeOAuthLogin } from "../features/auth/auth"; @@ -23,7 +23,6 @@ export const Route = createFileRoute("/oauth/callback")({ function CallbackPage() { const search = Route.useSearch(); - const navigate = useNavigate(); const [ err, setErr ] = useState(null); // ref guard:completeOAuthLogin 内部会消费 localStorage 中的 PKCE_VERIFIER / @@ -70,7 +69,12 @@ function CallbackPage() return; } completeOAuthLogin(search.code, search.state).then( - () => { if (!cancelled) { navigate({ to: "/" }); } }, + // 整页跳转(window.location.replace),不是路由软导航。Safari 下,从 + // Casdoor 回跳后那条客户端导航会复用 OAuth 流程遗留的 HTTP 连接,而这些 + // 连接在 Safari 里会卡死后续资源(setup.js / 头像)约 2 分钟——手动刷新即 + // 恢复,印证是连接状态问题。整页重载拿到全新连接,绕开该 bug;auth 已在 + // sessionStorage,同标签刷新存活。replace 不入历史,避免后退重触已消费的 code。 + () => { if (!cancelled) { window.location.replace("/"); } }, (e) => { showErrDeferred(e instanceof Error ? e.message : String(e)); }, );