80 lines
2.2 KiB
TypeScript
80 lines
2.2 KiB
TypeScript
import { useEffect } from 'react';
|
||
import { useNavigate, useLocation } from 'react-router-dom';
|
||
import { useAuth } from '@/contexts/AuthContext';
|
||
|
||
// 不需要登录的公共页面路径
|
||
const PUBLIC_PATHS = [
|
||
'/login',
|
||
'/register',
|
||
'/forgot-password',
|
||
'/reset-password',
|
||
'/404',
|
||
'/500'
|
||
];
|
||
|
||
/**
|
||
* 认证守卫Hook
|
||
* 用于在组件中检查用户是否已登录
|
||
* @param requireAuth 是否需要认证,默认为true
|
||
* @param redirectTo 未认证时重定向的路径,默认为'/login'
|
||
*/
|
||
export function useAuthGuard(requireAuth: boolean = true, redirectTo: string = '/login') {
|
||
const { isAuthenticated, isLoading } = useAuth();
|
||
const navigate = useNavigate();
|
||
const location = useLocation();
|
||
|
||
// 检查当前路径是否是公共页面
|
||
const isPublicPath = PUBLIC_PATHS.some(path =>
|
||
location.pathname.startsWith(path)
|
||
);
|
||
|
||
useEffect(() => {
|
||
// 如果正在加载,不进行任何跳转
|
||
if (isLoading) {
|
||
return;
|
||
}
|
||
|
||
// 如果需要认证但未登录且不是公共页面
|
||
if (requireAuth && !isAuthenticated && !isPublicPath) {
|
||
// 保存当前URL,登录后可以重定向回来
|
||
const returnUrl = encodeURIComponent(window.location.href);
|
||
navigate(`${redirectTo}?returnUrl=${returnUrl}`, { replace: true });
|
||
return;
|
||
}
|
||
|
||
// 如果已登录但在登录页面,重定向到首页
|
||
if (isAuthenticated && location.pathname === '/login') {
|
||
navigate('/', { replace: true });
|
||
return;
|
||
}
|
||
}, [isAuthenticated, isLoading, location.pathname, navigate, requireAuth, redirectTo, isPublicPath]);
|
||
|
||
return {
|
||
isAuthenticated,
|
||
isLoading,
|
||
isPublicPath,
|
||
// 是否应该显示内容
|
||
shouldRender: !isLoading && (isAuthenticated || isPublicPath || !requireAuth)
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 简单的认证检查Hook
|
||
* 只返回认证状态,不进行自动重定向
|
||
*/
|
||
export function useAuthCheck() {
|
||
const { isAuthenticated, isLoading } = useAuth();
|
||
const location = useLocation();
|
||
|
||
const isPublicPath = PUBLIC_PATHS.some(path =>
|
||
location.pathname.startsWith(path)
|
||
);
|
||
|
||
return {
|
||
isAuthenticated,
|
||
isLoading,
|
||
isPublicPath,
|
||
// 是否需要认证
|
||
requiresAuth: !isPublicPath
|
||
};
|
||
}
|