You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React JS中用户会话验证:JWT过期后如何重定向至登录页?

优化React Router中JWT令牌验证的实现方案

你的核心需求是在用户访问受保护路由(如仪表盘)时,验证JWT令牌的有效性,无效则重定向到登录页。现有代码虽然能运行,但存在重复请求、闪屏、重定向逻辑失效等问题,以下是更优的实现思路和代码:

现有代码的问题

  1. 直接在组件顶层调用user()异步函数,会导致组件每次渲染都发起请求,造成资源浪费。
  2. 初始isLogin为false,会先渲染<Navigate to="/auth-login" />,待请求返回后才更新状态,出现不必要的登录页闪屏。
  3. catch块中的<Navigate />完全无效,因为它是在异步函数内部的代码,并非组件返回的JSX。
  4. 没有处理请求加载状态,用户会看到空白或错误跳转的突兀体验。

优化方案

1. 用useEffect触发验证请求

仅在组件挂载时发起一次令牌验证请求,避免重复调用。

2. 增加加载状态

在请求过程中显示加载提示(如骨架屏、加载动画),提升用户体验。

3. 正确处理重定向逻辑

通过组件状态控制渲染结果,确保状态更新后正确跳转。

4. 可选:封装Axios拦截器统一处理令牌失效

在Axios实例中添加响应拦截器,全局捕获401/令牌无效的错误,直接触发重定向,减少重复代码。

优化后的代码实现

import React, { useState, useEffect } from "react";
import axios from "../../api/authAxios";
import { Navigate, Outlet } from "react-router-dom";

export default function PrivateAuth() {
  // 三个状态:是否已登录、是否在加载中、是否验证失败
  const [isAuthenticated, setIsAuthenticated] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const validateToken = async () => {
      try {
        const resp = await axios.get("/user");
        
        // 检查用户类型是否被禁止
        if (resp.data.data.user_type === process.env.REACT_APP_DISALLOW) {
          setIsAuthenticated(false);
          return;
        }
        
        // 验证成功
        setIsAuthenticated(true);
      } catch (error) {
        // 令牌无效、过期或其他错误,标记为未认证
        console.error(error.response?.data || "验证失败");
        setIsAuthenticated(false);
      } finally {
        // 请求完成,结束加载状态
        setIsLoading(false);
      }
    };

    validateToken();
  }, []);

  // 加载中时显示加载提示
  if (isLoading) {
    return <div>加载中...</div>; // 可替换为骨架屏或自定义加载组件
  }

  // 根据验证结果跳转或渲染受保护内容
  return isAuthenticated ? <Outlet /> : <Navigate to="/auth-login" replace />;
}

额外优化:Axios全局拦截器

如果多个地方都需要处理令牌失效,可以在authAxios中添加响应拦截器,统一处理:

// authAxios.js
import axios from "axios";

const authAxios = axios.create({
  baseURL: "/api",
});

// 响应拦截器
authAxios.interceptors.response.use(
  (response) => response,
  (error) => {
    // 捕获401(未授权)错误,直接重定向到登录页
    if (error.response?.status === 401) {
      window.location.href = "/auth-login";
    }
    return Promise.reject(error);
  }
);

export default authAxios;

这样在任何使用authAxios的请求中,只要返回401,都会自动跳转到登录页,无需在每个组件中重复处理。

内容的提问来源于stack exchange,提问作者Colorado Akpan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 21:37:38