bfe39e45a9
5. 修改统一认证登录和管理员登录是通过接口形式进行,存储返回的accessToken。 6. 修改交叉评查的部分样式
73 lines
2.2 KiB
TypeScript
73 lines
2.2 KiB
TypeScript
/**
|
||
* 服务端认证错误处理工具
|
||
*
|
||
* 用于在 Remix loader/action 中统一处理 AuthenticationError(token 过期)
|
||
*/
|
||
|
||
import { redirect } from "@remix-run/node";
|
||
|
||
/**
|
||
* 包装服务端异步函数,自动处理 AuthenticationError
|
||
*
|
||
* @param fn - 需要执行的异步函数
|
||
* @param pathname - 当前路径(用于保存重定向目标)
|
||
* @returns 函数执行结果,或在 token 过期时重定向到登录页
|
||
*
|
||
* @example
|
||
* // 在 loader 中使用
|
||
* export async function loader({ request }: LoaderFunctionArgs) {
|
||
* const url = new URL(request.url);
|
||
*
|
||
* return handleServerAuth(async () => {
|
||
* const { getUserSession } = await import("~/api/login/auth.server");
|
||
* const { frontendJWT } = await getUserSession(request);
|
||
*
|
||
* // 调用需要认证的 API
|
||
* const response = await getDocumentTypes({}, frontendJWT);
|
||
*
|
||
* return Response.json({ data: response.data });
|
||
* }, url.pathname);
|
||
* }
|
||
*/
|
||
export async function handleServerAuth<T>(
|
||
fn: () => Promise<T>,
|
||
pathname: string
|
||
): Promise<T> {
|
||
try {
|
||
return await fn();
|
||
} catch (error) {
|
||
// 检查是否是 AuthenticationError(token 过期)
|
||
if (error instanceof Error && error.name === 'AuthenticationError') {
|
||
console.warn(`⚠️ [Server Auth Handler] Token 过期,重定向到登录页 (from: ${pathname})`);
|
||
|
||
// 保存当前路径,登录后可以跳转回来
|
||
const redirectTo = pathname !== '/login' ? pathname : '/';
|
||
throw redirect(`/login?redirect=${encodeURIComponent(redirectTo)}`);
|
||
}
|
||
|
||
// 其他错误继续抛出
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查错误是否是 AuthenticationError
|
||
*
|
||
* @param error - 要检查的错误对象
|
||
* @returns 是否是 AuthenticationError
|
||
*/
|
||
export function isAuthenticationError(error: unknown): boolean {
|
||
return error instanceof Error && error.name === 'AuthenticationError';
|
||
}
|
||
|
||
/**
|
||
* 从 AuthenticationError 创建登录重定向
|
||
*
|
||
* @param pathname - 当前路径
|
||
* @returns Remix redirect Response
|
||
*/
|
||
export function redirectToLogin(pathname: string) {
|
||
const redirectTo = pathname !== '/login' ? pathname : '/';
|
||
return redirect(`/login?redirect=${encodeURIComponent(redirectTo)}`);
|
||
}
|