feat: 1. 修改完善全局路由检测。 2. 完善统一的token认证管理,token失效自动跳转到登录页。
This commit is contained in:
+40
-5
@@ -1,9 +1,9 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useLoaderData, useNavigate, useFetcher } from "@remix-run/react";
|
||||
import { type MetaFunction, type LoaderFunctionArgs, type ActionFunctionArgs, redirect } from "@remix-run/node";
|
||||
import { useLoaderData, useFetcher } from "@remix-run/react";
|
||||
import { type MetaFunction, type LoaderFunctionArgs, type ActionFunctionArgs } from "@remix-run/node";
|
||||
import { OAuthClient } from "~/api/login/oauth-client";
|
||||
import { CLIENT_OAUTH_CONFIG } from "~/config/api-config";
|
||||
import { getUserSession, getSession, createUserSession } from "~/api/login/auth.server";
|
||||
import { getSession, createUserSession } from "~/api/login/auth.server";
|
||||
import { loginWithPassword } from "~/api/login/login-client";
|
||||
import styles from "~/styles/pages/login.css?url";
|
||||
import { toastService } from "~/components/ui";
|
||||
@@ -88,7 +88,7 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
}, { status: 401 });
|
||||
}
|
||||
|
||||
const { access_token, user_info } = response.data;
|
||||
const { access_token, expires_in, issued_time, user_info } = response.data;
|
||||
|
||||
// 验证返回数据
|
||||
if (!access_token) {
|
||||
@@ -107,8 +107,22 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
}, { status: 500 });
|
||||
}
|
||||
|
||||
// 🔑 将后端返回的 issued_time 转换为时间戳(毫秒)
|
||||
let tokenIssuedAt = Date.now(); // 默认使用当前时间
|
||||
if (issued_time) {
|
||||
try {
|
||||
// 后端返回格式:"2025-11-18 17:41:06"
|
||||
// 转换为时间戳(毫秒)
|
||||
tokenIssuedAt = new Date(issued_time.replace(' ', 'T')).getTime();
|
||||
console.log("📅 [Login Action] 使用后端返回的签发时间:", issued_time, "→", tokenIssuedAt);
|
||||
} catch (error) {
|
||||
console.warn("⚠️ [Login Action] 无法解析 issued_time,使用当前时间:", error);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("✅ [Login Action] 登录成功,准备创建 session");
|
||||
console.log("👤 [Login Action] 用户角色:", user_info.user_role); // 应该是 "admin"
|
||||
console.log("⏰ [Login Action] Token 有效期:", expires_in, "秒 (", expires_in / 3600, "小时)");
|
||||
|
||||
// 获取当前 URL 用于构建 callback URL
|
||||
const url = new URL(request.url);
|
||||
@@ -137,6 +151,8 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
userRole: user_info.user_role,
|
||||
redirectTo: callbackUrl.toString(), // 先跳转到 callback 页面保存 token
|
||||
frontendJWT: access_token, // 保存到 Cookie Session
|
||||
tokenExpiresIn: expires_in,
|
||||
tokenIssuedAt: tokenIssuedAt, // 🔑 传递后端返回的签发时间
|
||||
userInfo: {
|
||||
user_id: user_info.user_id,
|
||||
username: user_info.username,
|
||||
@@ -161,7 +177,7 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
}
|
||||
|
||||
export default function Login() {
|
||||
const navigate = useNavigate();
|
||||
// const navigate = useNavigate();
|
||||
const loaderData = useLoaderData<typeof loader>();
|
||||
const fetcher = useFetcher<{ success: boolean; error?: string }>();
|
||||
const [isFlipped, setIsFlipped] = useState(false);
|
||||
@@ -268,6 +284,25 @@ export default function Login() {
|
||||
}, [fetcher.data]);
|
||||
|
||||
useEffect(() => {
|
||||
// 🔑 只在 token 过期时清理客户端存储
|
||||
// 检查 URL 参数中是否有 expired=true 标识
|
||||
if (typeof window !== 'undefined') {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const isExpired = urlParams.get('expired') === 'true';
|
||||
|
||||
if (isExpired) {
|
||||
// 只有在因为过期被重定向时才清除 localStorage
|
||||
localStorage.removeItem('access_token');
|
||||
localStorage.removeItem('user_info');
|
||||
console.log("🧹 [Login] Token 已过期,已清除客户端 token 数据");
|
||||
|
||||
// 清除 URL 中的 expired 参数,避免刷新页面时重复清除
|
||||
urlParams.delete('expired');
|
||||
const newUrl = window.location.pathname + (urlParams.toString() ? '?' + urlParams.toString() : '');
|
||||
window.history.replaceState({}, '', newUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// 检查OAuth配置是否完整(客户端不需要检查 clientSecret)
|
||||
if (!CLIENT_OAUTH_CONFIG.serverUrl || !CLIENT_OAUTH_CONFIG.clientId) {
|
||||
console.error("OAuth2.0配置不完整:", CLIENT_OAUTH_CONFIG);
|
||||
|
||||
Reference in New Issue
Block a user