refactor(auth): standardize authorization token handling

- Replace 'token' with 'Authorization' in localStorage keys for consistency
- Update auth guard, request interceptor and login hooks to use new key
- Add updateAuthorization method to auth hook for better state management
This commit is contained in:
2025-10-11 14:20:56 +08:00
parent 650c41dc41
commit 6f0332c1ff
3 changed files with 69 additions and 57 deletions

View File

@@ -11,8 +11,8 @@ const AuthGuard: React.FC<AuthGuardProps> = ({ children }) => {
const navigate = useNavigate(); const navigate = useNavigate();
// 直接从localStorage检查token避免React状态更新的延迟 // 直接从localStorage检查token避免React状态更新的延迟
const token = localStorage.getItem('token'); const authorization = localStorage.getItem('Authorization');
const isAuthenticated = !!token; const isAuthenticated = !!authorization;
const isLoginPage = location.pathname === '/login'; const isLoginPage = location.pathname === '/login';
useEffect(() => { useEffect(() => {

View File

@@ -11,7 +11,7 @@ import { rsaPsw } from '../utils/encryption';
export const useOAuthCallback = () => { export const useOAuthCallback = () => {
const [searchParams, setSearchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
const navigate = useNavigate(); const navigate = useNavigate();
const error = searchParams.get('error'); const error = searchParams.get('error');
const newSearchParams: URLSearchParams = useMemo( const newSearchParams: URLSearchParams = useMemo(
() => new URLSearchParams(searchParams.toString()), () => new URLSearchParams(searchParams.toString()),
@@ -33,7 +33,7 @@ export const useOAuthCallback = () => {
const auth = searchParams.get('auth'); const auth = searchParams.get('auth');
if (auth) { if (auth) {
// 存储认证信息 // 存储认证信息
localStorage.setItem('token', auth); localStorage.setItem('Authorization', auth);
newSearchParams.delete('auth'); newSearchParams.delete('auth');
setSearchParams(newSearchParams); setSearchParams(newSearchParams);
navigate('/'); navigate('/');
@@ -56,36 +56,40 @@ export const useAuth = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
const [isAuthenticated, setIsAuthenticated] = useState<boolean | null>(null);
const [userInfo, setUserInfo] = useState<any>(null); const [userInfo, setUserInfo] = useState<any>(null);
const [token, setToken] = useState<string | null>(null); const [token, setToken] = useState<string | null>(null);
const [authorization, setAuthorization] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
// OAuth回调处理 // OAuth回调处理
const auth = useOAuthCallback(); const auth = useOAuthCallback();
const isAuthenticated = useMemo(() => authorization !== null && authorization !== '', [authorization]);
// 检查认证状态 // 检查认证状态
const checkAuthStatus = () => { const checkAuthStatus = () => {
try { try {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
const storedAuthorization = localStorage.getItem('Authorization');
const storedUserInfo = localStorage.getItem('userInfo'); const storedUserInfo = localStorage.getItem('userInfo');
if (storedToken) { if (storedAuthorization) {
setToken(storedToken); setToken(storedToken);
setIsAuthenticated(true); setAuthorization(storedAuthorization);
if (storedUserInfo) { if (storedUserInfo) {
setUserInfo(JSON.parse(storedUserInfo)); setUserInfo(JSON.parse(storedUserInfo));
} }
} else { } else {
setToken(null); setToken(null);
setIsAuthenticated(false); setAuthorization(null);
setUserInfo(null); setUserInfo(null);
} }
} catch (error) { } catch (error) {
console.error('Error checking auth status:', error); console.error('Error checking auth status:', error);
setToken(null); setToken(null);
setIsAuthenticated(false); setAuthorization(null);
setUserInfo(null); setUserInfo(null);
} finally { } finally {
setIsLoading(false); setIsLoading(false);
@@ -97,16 +101,19 @@ export const useAuth = () => {
localStorage.removeItem('token'); localStorage.removeItem('token');
localStorage.removeItem('userInfo'); localStorage.removeItem('userInfo');
setToken(null); setToken(null);
setIsAuthenticated(false);
setUserInfo(null); setUserInfo(null);
navigate('/login'); navigate('/login');
}; };
const updateAuthorization = (newAuthorization: string) => {
setAuthorization(newAuthorization);
localStorage.setItem('Authorization', newAuthorization);
};
// 更新认证状态 // 更新认证状态
const updateAuthStatus = (newToken: string, newUserInfo: any) => { const updateAuthStatus = (newToken: string, newUserInfo: any) => {
setToken(newToken); setToken(newToken);
setUserInfo(newUserInfo); setUserInfo(newUserInfo);
setIsAuthenticated(true);
localStorage.setItem('token', newToken); localStorage.setItem('token', newToken);
localStorage.setItem('userInfo', JSON.stringify(newUserInfo)); localStorage.setItem('userInfo', JSON.stringify(newUserInfo));
}; };
@@ -142,6 +149,7 @@ export const useAuth = () => {
isLoading, isLoading,
checkAuthStatus, checkAuthStatus,
logout, logout,
updateAuthorization,
updateAuthStatus, updateAuthStatus,
redirectToLogin, redirectToLogin,
redirectAfterLogin, redirectAfterLogin,
@@ -171,33 +179,37 @@ export const useLogin = () => {
const login = async (data: LoginFormData) => { const login = async (data: LoginFormData) => {
setIsLoading(true); setIsLoading(true);
try { try {
// RSA加密密码 // RSA加密密码
const encryptedPassword = rsaPsw(data.password); const encryptedPassword = rsaPsw(data.password);
const response = await userService.login({ const response = await userService.login({
email: data.email.trim(), email: data.email.trim(),
password: encryptedPassword password: encryptedPassword
}); });
const { data: res = {} } = response; const { data: res = {}, headers } = response;
const authorization: string = headers['authorization'] ?? headers['Authorization'] ?? '';
localStorage.setItem('Authorization', authorization);
const { code, message } = res; const { code, message } = res;
if (code === 0) { if (code === 0) {
// 登录成功处理token和用户信息 // 登录成功处理token和用户信息
const { data: userData } = res; const { data: userData } = res;
const token = userData.access_token; const token: string = userData.access_token;
const userInfo = { const userInfo = {
...userData, ...userData,
avatar: userData.avatar, avatar: userData.avatar,
name: userData.nickname, name: userData.nickname,
email: userData.email, email: userData.email,
}; };
// 同步更新localStorage // 同步更新localStorage
localStorage.setItem('token', token); localStorage.setItem('token', token);
localStorage.setItem('userInfo', JSON.stringify(userInfo)); localStorage.setItem('userInfo', JSON.stringify(userInfo));
// 直接进行重定向不依赖React状态更新 // 直接进行重定向不依赖React状态更新
const redirectUrl = searchParams.get('redirect'); const redirectUrl = searchParams.get('redirect');
if (redirectUrl) { if (redirectUrl) {
@@ -205,20 +217,20 @@ export const useLogin = () => {
} else { } else {
navigate('/', { replace: true }); navigate('/', { replace: true });
} }
return { success: true }; return { success: true };
} else { } else {
// 登录失败 // 登录失败
return { return {
success: false, success: false,
error: message || t('login.loginFailed') error: message || t('login.loginFailed')
}; };
} }
} catch (error: any) { } catch (error: any) {
// 处理网络错误或其他异常 // 处理网络错误或其他异常
return { return {
success: false, success: false,
error: error.message || t('login.networkError') error: error.message || t('login.networkError')
}; };
} finally { } finally {
setIsLoading(false); setIsLoading(false);
@@ -237,11 +249,11 @@ export const useRegister = () => {
const register = async (data: RegisterFormData) => { const register = async (data: RegisterFormData) => {
setIsLoading(true); setIsLoading(true);
try { try {
// RSA加密密码 // RSA加密密码
const encryptedPassword = rsaPsw(data.password); const encryptedPassword = rsaPsw(data.password);
const response = await userService.register({ const response = await userService.register({
nickname: data.nickname, nickname: data.nickname,
email: data.email.trim(), email: data.email.trim(),
@@ -250,25 +262,25 @@ export const useRegister = () => {
const { data: res = {} } = response; const { data: res = {} } = response;
const { code, message } = res; const { code, message } = res;
if (code === 0) { if (code === 0) {
// 注册成功 // 注册成功
return { return {
success: true, success: true,
email: data.email email: data.email
}; };
} else { } else {
// 注册失败 // 注册失败
return { return {
success: false, success: false,
error: message || t('login.registerFailed') error: message || t('login.registerFailed')
}; };
} }
} catch (error: any) { } catch (error: any) {
// 处理网络错误或其他异常 // 处理网络错误或其他异常
return { return {
success: false, success: false,
error: error.message || t('login.networkError') error: error.message || t('login.networkError')
}; };
} finally { } finally {
setIsLoading(false); setIsLoading(false);
@@ -335,23 +347,23 @@ export const useLoginForm = () => {
error, error,
loginForm, loginForm,
registerForm, registerForm,
// 表单操作 // 表单操作
handleTabChange, handleTabChange,
switchToLogin, switchToLogin,
setFormError, setFormError,
clearError, clearError,
// 表单验证规则 // 表单验证规则
loginValidation: { loginValidation: {
email: { email: {
required: t('login.emailPlaceholder'), required: t('login.emailPlaceholder'),
pattern: { pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: t('login.emailInvalid') message: t('login.emailInvalid')
} }
}, },
password: { password: {
required: t('login.passwordPlaceholder'), required: t('login.passwordPlaceholder'),
minLength: { minLength: {
value: 6, value: 6,
@@ -360,21 +372,21 @@ export const useLoginForm = () => {
} }
}, },
registerValidation: { registerValidation: {
nickname: { nickname: {
required: t('login.nicknamePlaceholder'), required: t('login.nicknamePlaceholder'),
minLength: { minLength: {
value: 2, value: 2,
message: t('login.nicknameMinLength') message: t('login.nicknameMinLength')
} }
}, },
email: { email: {
required: t('login.emailPlaceholder'), required: t('login.emailPlaceholder'),
pattern: { pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: t('login.emailInvalid') message: t('login.emailInvalid')
} }
}, },
password: { password: {
required: t('login.passwordPlaceholder'), required: t('login.passwordPlaceholder'),
minLength: { minLength: {
value: 8, value: 8,
@@ -396,18 +408,18 @@ export const useLoginPage = () => {
const handleLogin = async (data: LoginFormData) => { const handleLogin = async (data: LoginFormData) => {
formHook.clearError(); formHook.clearError();
const result = await loginHook.login(data); const result = await loginHook.login(data);
if (!result.success && result.error) { if (!result.success && result.error) {
formHook.setFormError(result.error); formHook.setFormError(result.error);
} }
return result; return result;
}; };
const handleRegister = async (data: RegisterFormData) => { const handleRegister = async (data: RegisterFormData) => {
formHook.clearError(); formHook.clearError();
const result = await registerHook.register(data); const result = await registerHook.register(data);
if (result.success) { if (result.success) {
// 注册成功,切换到登录表单并填入邮箱 // 注册成功,切换到登录表单并填入邮箱
formHook.registerForm.reset(); formHook.registerForm.reset();
@@ -415,7 +427,7 @@ export const useLoginPage = () => {
} else if (result.error) { } else if (result.error) {
formHook.setFormError(result.error); formHook.setFormError(result.error);
} }
return result; return result;
}; };
@@ -424,7 +436,7 @@ export const useLoginPage = () => {
return { return {
// 表单相关 // 表单相关
...formHook, ...formHook,
// 提交处理 // 提交处理
handleLogin, handleLogin,
handleRegister, handleRegister,

View File

@@ -47,12 +47,12 @@ export type ResultCode =
// 获取授权token // 获取授权token
const getAuthorization = (): string => { const getAuthorization = (): string => {
return localStorage.getItem('token') || ''; return localStorage.getItem(Authorization) || '';
}; };
// 重定向到登录页 // 重定向到登录页
const redirectToLogin = (): void => { const redirectToLogin = (): void => {
localStorage.removeItem('token'); localStorage.removeItem(Authorization);
window.location.href = '/login'; window.location.href = '/login';
}; };
@@ -94,9 +94,9 @@ request.interceptors.request.use(
} }
// 添加授权头 // 添加授权头
const token = getAuthorization(); const authorization = getAuthorization();
if (token && !config.headers?.skipToken) { if (authorization && !config.headers?.skipToken) {
config.headers[Authorization] = token; config.headers.Authorization = authorization;
} }
return config; return config;