fix(auth): prevent unauthorized requests and improve logout handling
This commit is contained in:
@@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import userService from '../services/user_service';
|
import userService from '../services/user_service';
|
||||||
import { rsaPsw } from '../utils/encryption';
|
import { rsaPsw } from '../utils/encryption';
|
||||||
|
import { Authorization, Token, UserInfo } from '@/constants/authorization';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OAuth回调处理Hook
|
* OAuth回调处理Hook
|
||||||
@@ -98,9 +99,9 @@ export const useAuth = () => {
|
|||||||
|
|
||||||
// 登出功能
|
// 登出功能
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
localStorage.removeItem('token');
|
localStorage.removeItem(Authorization);
|
||||||
localStorage.removeItem('Authorization');
|
localStorage.removeItem(Token);
|
||||||
localStorage.removeItem('userInfo');
|
localStorage.removeItem(UserInfo);
|
||||||
setToken(null);
|
setToken(null);
|
||||||
setAuthorization(null);
|
setAuthorization(null);
|
||||||
setUserInfo(null);
|
setUserInfo(null);
|
||||||
@@ -191,7 +192,7 @@ export const useLogin = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { data: res = {}, headers } = response;
|
const { data: res = {}, headers } = response;
|
||||||
|
|
||||||
const authorization: string = headers['authorization'] ?? headers['Authorization'] ?? '';
|
const authorization: string = headers['authorization'] ?? headers['Authorization'] ?? '';
|
||||||
|
|
||||||
localStorage.setItem('Authorization', authorization);
|
localStorage.setItem('Authorization', authorization);
|
||||||
|
|||||||
@@ -18,7 +18,11 @@ export function useProfileSetting() {
|
|||||||
const { fetchUserInfo, userInfo } = useUserData();
|
const { fetchUserInfo, userInfo } = useUserData();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchUserInfo();
|
// 仅在已登录情况下才获取用户信息,避免登录页触发401导致重复跳转
|
||||||
|
const authorization = localStorage.getItem('Authorization');
|
||||||
|
if (authorization && authorization !== '') {
|
||||||
|
fetchUserInfo();
|
||||||
|
}
|
||||||
}, [fetchUserInfo]);
|
}, [fetchUserInfo]);
|
||||||
|
|
||||||
const updateUserInfo = async (newUserInfo: Partial<IUserInfo>) => {
|
const updateUserInfo = async (newUserInfo: Partial<IUserInfo>) => {
|
||||||
@@ -58,6 +62,12 @@ export function useLanguageSetting() {
|
|||||||
try {
|
try {
|
||||||
// LanguageAbbreviation to language
|
// LanguageAbbreviation to language
|
||||||
const translatedLanguage = LanguageAbbreviationKeysMap[language];
|
const translatedLanguage = LanguageAbbreviationKeysMap[language];
|
||||||
|
const authorization = localStorage.getItem('Authorization');
|
||||||
|
// 未登录时仅本地切换语言,不请求后端,避免401导致跳转
|
||||||
|
if (!authorization || authorization === '') {
|
||||||
|
setLanguage(translatedLanguage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
await updateUserInfo({ language: translatedLanguage });
|
await updateUserInfo({ language: translatedLanguage });
|
||||||
setLanguage(translatedLanguage);
|
setLanguage(translatedLanguage);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Authorization } from '@/constants/authorization';
|
import { Authorization, Token, UserInfo } from '@/constants/authorization';
|
||||||
import type { ResponseType } from '@/interfaces/database/base';
|
import type { ResponseType } from '@/interfaces/database/base';
|
||||||
import i18n from '@/locales';
|
import i18n from '@/locales';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
@@ -51,10 +51,24 @@ const getAuthorization = (): string => {
|
|||||||
return localStorage.getItem(Authorization) || '';
|
return localStorage.getItem(Authorization) || '';
|
||||||
};
|
};
|
||||||
|
|
||||||
// 重定向到登录页
|
// 重定向到登录页(若已在登录页则不重复刷新,避免死循环)
|
||||||
const redirectToLogin = (): void => {
|
const redirectToLogin = (): void => {
|
||||||
localStorage.removeItem(Authorization);
|
try {
|
||||||
window.location.href = '/login';
|
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
|
// 转换对象键为snake_case
|
||||||
|
|||||||
Reference in New Issue
Block a user