From e7670c7cefca533af9a9958a3ca1af1b7b39bb7d Mon Sep 17 00:00:00 2001 From: shay7sev Date: Mon, 9 Mar 2026 13:57:47 +0800 Subject: [PATCH] fix(api): fix token handler --- api/fetch.ts | 31 ++++++++---------- app/api/transfer/[path]/route.ts | 55 ++++++++++++++++++++------------ components/layout/AppLayout.tsx | 2 ++ components/login/libs/cookie.ts | 8 +++-- 4 files changed, 55 insertions(+), 41 deletions(-) diff --git a/api/fetch.ts b/api/fetch.ts index 6bfbba9..5bb80c2 100644 --- a/api/fetch.ts +++ b/api/fetch.ts @@ -17,6 +17,7 @@ fetch 参数: "use client" import { useUserStore } from "@/app/store/user" +import { usePermissionStore } from "@/components/label/store/auth" import { deleteCookie, refreshKey } from "@/components/login/api" import { isNumber } from "@/libs/util" @@ -40,6 +41,7 @@ interface OptionsProps { async function httpfetch(options: OptionsProps): Promise { const { removeUserInfo, refreshToken } = useUserStore.getState() + const { logout } = usePermissionStore.getState() const access_token = useUserStore.getState().access_token const refresh_token = useUserStore.getState().refresh_token @@ -186,24 +188,19 @@ async function httpfetch(options: OptionsProps): Promise { return options.isDownload ? retry_response.blob() : retry_response.json() - } else { - const { code } = refreshResponse - if (code === 406) { - try { - await deleteCookie() - } catch (error) { - rejected(error) - } finally { - // 清空身份信息并跳转至登录页面 - removeUserInfo() - window.location.href = "/login" - } - } else { - throw new Error("重新获取token失败!") - } } } catch (error) { rejected(error) + try { + await deleteCookie() + } catch (error) { + rejected(error) + } finally { + // 清空身份信息并跳转至登录页面 + removeUserInfo() + logout() + window.location.href = "/login" + } } } else if (status === 403) { if ( @@ -271,8 +268,7 @@ async function httpfetch(options: OptionsProps): Promise { ? retry_response.blob() : retry_response.json() } else { - const { code } = refreshResponse - if (code === 406) { + if (refreshResponse.code === 406) { try { await deleteCookie() } catch (error) { @@ -280,6 +276,7 @@ async function httpfetch(options: OptionsProps): Promise { } finally { // 清空身份信息并跳转至登录页面 removeUserInfo() + logout() window.location.href = "/login" } } else { diff --git a/app/api/transfer/[path]/route.ts b/app/api/transfer/[path]/route.ts index 9c15efd..60907e3 100644 --- a/app/api/transfer/[path]/route.ts +++ b/app/api/transfer/[path]/route.ts @@ -46,32 +46,45 @@ export async function POST(req: any) { } ) } - const userData = await genAccessToken(req) - const authorization = `bearer ${userData?.access_token}` + let fetchOptions: any = {} - const fetchOptions: any = { - method, - headers: { - "content-type": "application/json", - authorization: authorization, - }, - } - - if (method === "POST" || method === "PUT") { - let refreshBody = JSON.stringify({ - ...JSON.parse(data), - token: userData?.refresh_token || "", - }) - fetchOptions.body = isRefresh ? refreshBody : data + if (isRefresh) { + if (!userData?.refresh_token) { + return NextResponse.json( + { message: "Refresh token is empty", code: 406 }, + { status: 200 } + ) + } + fetchOptions = { + method, + headers: { + "content-type": "application/json", + }, + body: JSON.stringify({ + token: userData?.refresh_token, + }), + } } else { - if (isParamsValid(data)) { - let test = "" - for (const [key, value] of Object.entries(data)) { - test += `&${key}=${value}` + const authorization = `bearer ${userData?.access_token}` + fetchOptions = { + method, + headers: { + "content-type": "application/json", + authorization: authorization, + }, + } + if (method === "POST" || method === "PUT") { + fetchOptions.body = data + } else { + if (isParamsValid(data)) { + let test = "" + for (const [key, value] of Object.entries(data)) { + test += `&${key}=${value}` + } + url += `?${test}` } - url += `?${test}` } } diff --git a/components/layout/AppLayout.tsx b/components/layout/AppLayout.tsx index 6b07776..d1d25aa 100644 --- a/components/layout/AppLayout.tsx +++ b/components/layout/AppLayout.tsx @@ -32,6 +32,7 @@ import headerLinkClasses from "./HeaderLink.module.css" import { useUserStore } from "@/app/store/user" import { usePathname, useRouter } from "next/navigation" +import { usePermissionStore } from "../label/store/auth" import { deleteCookie } from "../login/api" import { MenuItem, withoutLayoutRoutes } from "./common" import { ClientIcon } from "./components/ClientIcon" @@ -140,6 +141,7 @@ export default function AppLayout({ const handleLogout = async () => { useUserStore.getState().removeUserInfo() + usePermissionStore.getState().logout() process.env.NEXT_PUBLIC_OUTPUT_TYPE === "standalone" && (await deleteCookie()) router.push("/login") diff --git a/components/login/libs/cookie.ts b/components/login/libs/cookie.ts index c1e94d4..9fbff6e 100644 --- a/components/login/libs/cookie.ts +++ b/components/login/libs/cookie.ts @@ -1,8 +1,8 @@ import { ResultData } from "@/api/typing" +import { Login } from "@/components/login/api/types" import redis from "@/components/login/libs/redis" import { encrypt, generateKeyFromEnv } from "@/components/login/libs/session" import { cookies } from "next/headers" -import { Login } from "@/components/login/api/types" export const handleLoginData = async (props: { clientIP: string @@ -75,8 +75,10 @@ export const handleRefreshToken = async (props: { ...data, message: { ...data.message, - access_token: "", - refresh_token: "", + // access_token: "", + // refresh_token: "", + access: "", + refresh: "", }, } }