From 5bacd454199f290e585ba20d2af0f8ea2e6638d4 Mon Sep 17 00:00:00 2001 From: "guangfei.zhao" Date: Fri, 14 Nov 2025 20:51:24 +0800 Subject: [PATCH] fix(auth): prevent unauthorized requests and improve logout handling --- src/hooks/login-hooks.ts | 9 +++++---- src/hooks/setting-hooks.ts | 12 +++++++++++- src/utils/request.ts | 22 ++++++++++++++++++---- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/hooks/login-hooks.ts b/src/hooks/login-hooks.ts index 2f1a15c..cc440b1 100644 --- a/src/hooks/login-hooks.ts +++ b/src/hooks/login-hooks.ts @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next'; import { useForm } from 'react-hook-form'; import userService from '../services/user_service'; import { rsaPsw } from '../utils/encryption'; +import { Authorization, Token, UserInfo } from '@/constants/authorization'; /** * OAuth回调处理Hook @@ -98,9 +99,9 @@ export const useAuth = () => { // 登出功能 const logout = () => { - localStorage.removeItem('token'); - localStorage.removeItem('Authorization'); - localStorage.removeItem('userInfo'); + localStorage.removeItem(Authorization); + localStorage.removeItem(Token); + localStorage.removeItem(UserInfo); setToken(null); setAuthorization(null); setUserInfo(null); @@ -191,7 +192,7 @@ export const useLogin = () => { }); const { data: res = {}, headers } = response; - + const authorization: string = headers['authorization'] ?? headers['Authorization'] ?? ''; localStorage.setItem('Authorization', authorization); diff --git a/src/hooks/setting-hooks.ts b/src/hooks/setting-hooks.ts index 6231ed9..6f729ad 100644 --- a/src/hooks/setting-hooks.ts +++ b/src/hooks/setting-hooks.ts @@ -18,7 +18,11 @@ export function useProfileSetting() { const { fetchUserInfo, userInfo } = useUserData(); useEffect(() => { - fetchUserInfo(); + // 仅在已登录情况下才获取用户信息,避免登录页触发401导致重复跳转 + const authorization = localStorage.getItem('Authorization'); + if (authorization && authorization !== '') { + fetchUserInfo(); + } }, [fetchUserInfo]); const updateUserInfo = async (newUserInfo: Partial) => { @@ -58,6 +62,12 @@ export function useLanguageSetting() { try { // LanguageAbbreviation to language const translatedLanguage = LanguageAbbreviationKeysMap[language]; + const authorization = localStorage.getItem('Authorization'); + // 未登录时仅本地切换语言,不请求后端,避免401导致跳转 + if (!authorization || authorization === '') { + setLanguage(translatedLanguage); + return; + } await updateUserInfo({ language: translatedLanguage }); setLanguage(translatedLanguage); } catch (error) { diff --git a/src/utils/request.ts b/src/utils/request.ts index f882476..d6e5334 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -1,4 +1,4 @@ -import { Authorization } from '@/constants/authorization'; +import { Authorization, Token, UserInfo } from '@/constants/authorization'; import type { ResponseType } from '@/interfaces/database/base'; import i18n from '@/locales'; import axios from 'axios'; @@ -51,10 +51,24 @@ const getAuthorization = (): string => { return localStorage.getItem(Authorization) || ''; }; -// 重定向到登录页 +// 重定向到登录页(若已在登录页则不重复刷新,避免死循环) const redirectToLogin = (): void => { - localStorage.removeItem(Authorization); - window.location.href = '/login'; + try { + localStorage.removeItem(Authorization); + localStorage.removeItem(Token); + localStorage.removeItem(UserInfo); + const currentPath = `${window.location.pathname}${window.location.search}`; + logger.info('redirectToLogin() invoked', { currentPath }); + // 已在登录页则不再刷新,交由路由守卫处理 + if (window.location.pathname === '/login') { + logger.info('Already on /login, skip hard redirect'); + return; + } + window.location.href = `/login?redirect=${encodeURIComponent(currentPath)}`; + } catch (e) { + logger.warn('redirectToLogin() exception fallback to /login'); + window.location.href = '/login'; + } }; // 转换对象键为snake_case