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

React+Node.js登录后JWT验证异常:刷新后恢复正常

问题分析与解决:登录跳转后Axios请求无Token,刷新恢复正常

问题场景

React前端+Node.js后端应用,用户登录成功后前端将accessToken存入localStorage(已验证有效),但跳转至/admin页面时,后端admin_auth中间件获取到的token为null,触发JsonWebTokenError: jwt malformed;刷新页面后,token验证完全正常。

相关代码

前端登录成功逻辑

if (res.status === 200) {
  localStorage.setItem("token", res.data.accessToken)
  console.log(res.data)
  dispatch(login(res.data.user))
  navigate("/admin")
}

Axios实例配置

export default axios.create({
  baseURL: `${process.env.REACT_APP_API_URL}`,
  headers: {
    token: `${localStorage.getItem("token")}`, // 初始化时可能为空,刷新后正常
  },
})

后端路由

router.get("/", admin_auth, GET_ALL_CATEGORIES);

admin_auth中间件

const admin_auth = (req, res, next) => {
  const token = req.headers["token"];
  console.log(token) // 刚登录时为NULL;刷新后token有效
  if (token) {
    console.log(token + " TOKEN ");
    jwt.verify(token, process.env.SECRET_KEY, (err, user) => {
      // ...更多代码
    })
  }
}

核心原因

你创建Axios实例的时机是应用初始化阶段,此时localStorage里还没有token,所以实例的headers.token被设置为null。登录成功后虽然把token存进了localStorage,但已经创建好的Axios实例不会自动更新headers,跳转/admin时发起的请求用的还是旧的实例,自然带不上有效token。

而刷新页面时,应用会重新初始化,此时localStorage里已经有token了,新创建的Axios实例就能正确带上token,所以验证正常。

解决方案

方案1:使用Axios请求拦截器(推荐)

每次发起请求前动态从localStorage获取token,确保请求头始终携带最新的token:

const axiosInstance = axios.create({
  baseURL: `${process.env.REACT_APP_API_URL}`,
});

// 添加请求拦截器
axiosInstance.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem("token");
    if (token) {
      config.headers.token = token;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

export default axiosInstance;

方案2:登录成功后手动更新Axios实例的headers

登录成功后直接修改已创建的Axios实例的默认headers:

// 假设你的Axios实例导出为axiosInstance
import axiosInstance from './path/to/axiosInstance';

// 登录成功逻辑里添加
if (res.status === 200) {
  const token = res.data.accessToken;
  localStorage.setItem("token", token);
  // 更新Axios实例的默认headers
  axiosInstance.defaults.headers.token = token;
  dispatch(login(res.data.user))
  navigate("/admin")
}

方案3:结合状态管理(如Redux)存储token

把token存在Redux等状态管理工具中,请求时从状态里获取:

// 在Axios请求拦截器中从Redux获取token
import { store } from './path/to/store';

axiosInstance.interceptors.request.use(
  (config) => {
    const { token } = store.getState().auth;
    if (token) {
      config.headers.token = token;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:35:34