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

React应用Service Layer创建后API异常:登录JWT格式错误刷新恢复

问题描述

在React应用中创建Service Layer后,Node.js API出现连接异常:登录时返回500内部服务器错误,提示jwt malformed,但刷新页面后可正常获取服务器响应。

项目文件夹结构

index.html
└── src
    ├── Components
    │   ├── Pages
    │   │   ├── Home.jsx
    │   │   ├── Provider.jsx
    │   │   ├── login.jsx
    │   │   ├── signup.jsx
    │   │   ...
    │   ├── ProviderComponents
    │   │   ├── WorkListProvider.jsx
    │   │   ...
    ├── Context
    │   └── UserContext.jsx
    └── Services
        └── Api
            ├── authService.js
            ├── config
            │   └── axiosConfig.js
            └── providerService.js

相关代码

src/Services/Api/config/axiosConfig.js

import axios from "axios";
import Cookies from "js-cookie";
const token = Cookies.get("token");

// 创建axios实例
export const api = axios.create({
  baseURL: import.meta.env.VITE_API_URL,
  headers: {
    Authorization : `Bearer ${token}`
  },
});


const errorHandler = (error) => {
  const statusCode = error.response?.status;

  if (statusCode && statusCode !== 401) {
    throw error
  }

  return Promise.reject(error);
};


api.interceptors.response.use(undefined, (error) => {
  return errorHandler(error);
});

src/Services/Api/providerService.js

import { api } from "./config/axiosConfig";

export const providerService = {
  getJobs: async () => {
    const response = await api.request({
      url: "/provider/myJobs",
      method: "GET",
    });
    return response.data;
  },
  // 其他服务方法
}

src/Components/providerComponents/WorkListProvider.jsx(服务调用逻辑)

useEffect(() => {
  providerService
    .getJobs()
    .then((workList) => {
      setWorkData(workList);
    })
    .catch((error) => {
      console.error(error);
    });
}, []);

src/Services/Api/authService.js

import { api } from "./config/axiosConfig";

export const authService = {
  login: async (data) => {
    const response = await api.request({
      url: `/login`,
      data,
      method: "POST",
    });
    console.log(response.data)
    return response.data;
  },
  // 其他服务方法
};

src/Components/Pages/login.jsx(登录逻辑)

const handleSubmit = (e) => {
  e.preventDefault();
  authService
    .login(values)
    .then((response) => {
      Cookies.set("token", response.token, { expires: 1 });
      changeLoggedIn(true);
      navigate("/");
    })
    .catch((error) => setErrorMessage(error.response.data.data.error));
};

问题原因及修复

核心原因

axios实例创建时,直接将Cookies.get("token")赋值给Authorization头。此时用户尚未登录,token不存在,导致请求头中出现Bearer undefined,后端解析JWT时触发jwt malformed错误。刷新页面后,cookie已存在,token被正确读取,请求恢复正常。

修复方案

方案1:用请求拦截器动态注入token(推荐)

修改axiosConfig.js,移除实例初始化时的Authorization配置,添加请求拦截器,每次请求前动态获取并注入token:

import axios from "axios";
import Cookies from "js-cookie";

// 创建axios实例,不预设Authorization头
export const api = axios.create({
  baseURL: import.meta.env.VITE_API_URL,
});

// 请求拦截器:每次请求前自动添加token(如果存在)
api.interceptors.request.use(
  (config) => {
    const token = Cookies.get("token");
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

const errorHandler = (error) => {
  const statusCode = error.response?.status;
  if (statusCode && statusCode !== 401) {
    throw error;
  }
  return Promise.reject(error);
};

api.interceptors.response.use(undefined, errorHandler);

方案2:登录成功后手动更新axios默认头

修改login.jsx的登录成功逻辑,手动更新axios实例的默认Authorization头:

const handleSubmit = (e) => {
  e.preventDefault();
  authService
    .login(values)
    .then((response) => {
      const token = response.token;
      Cookies.set("token", token, { expires: 1 });
      // 更新axios实例的默认授权头
      api.defaults.headers.common.Authorization = `Bearer ${token}`;
      changeLoggedIn(true);
      navigate("/");
    })
    .catch((error) => setErrorMessage(error.response.data.data.error));
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 09:58:11