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

React调用Node.js后端接口遇401未授权问题求助

问题:React请求接口返回401未授权,登录后TOKEN需刷新页面才显示

从数据库获取订单数据时遇到401(Unauthorized)错误,该接口在Postman中可正常调用,但React项目中存在以下问题:

  • 登录后控制台打印TOKEN为undefined
  • 刷新页面后才能看到正确的TOKEN值

相关代码

Order.jsx(React组件)

import { userRequest } from "../../requestMethods";
import { useEffect, useState } from "react";

const [orders, setOrders] = useState([]);

useEffect(() => {
  const getOrders= async () => {
    try {
      const res = await userRequest.get("orders");
      setOrders(res.data);
    } catch {}
  };
  getOrders();
}, []);
console.log(orders);

requestMethods.js(Axios配置文件)

import axios from "axios";

const BASE_URL = "http://localhost:5000/api/";

const user = JSON.parse(localStorage.getItem("persist:root"))?.user;

const currentUser = user && JSON.parse(user).currentUser;

const TOKEN = currentUser?.accessToken;

console.log(TOKEN);

export const publicRequest = axios.create({
  baseURL: BASE_URL,
});

export const userRequest = axios.create({
  baseURL: BASE_URL,
  header: { token: `Bearer ${TOKEN}` },
});

order.js(Node.js后端路由)

const Order = require("../models/Order");
const {
  verifyToken,
  verifyTokenAndAuthorization,
  verifyTokenAndAdmin,
} = require("./verifyToken");

const router = require("express").Router();

router.get("/", verifyTokenAndAdmin, async (req, res) => {
  try {
    const orders = await Order.find();
    res.status(200).json(orders);
  } catch (err) {
    res.status(500).json(err);
  }
});

问题原因分析

  1. TOKEN初始化时机问题:requestMethods.js中的TOKEN是在模块加载时计算的,登录后localStorage更新,但模块不会重新执行,因此TOKEN始终是初始的undefined,只有刷新页面后模块重新加载,才能拿到最新的TOKEN。
  2. Axios配置错误:userRequest中的header拼写错误,应为复数headers,导致请求头未正确携带TOKEN。
  3. 请求发起过早:登录后localStorage还未完成写入,useEffect就已发起请求,此时TOKEN还未生成。

解决方案

1. 修正Axios配置,改用请求拦截器动态获取TOKEN

修改requestMethods.js,每次请求前从localStorage读取最新TOKEN,避免模块初始化时的静态值问题:

import axios from "axios";

const BASE_URL = "http://localhost:5000/api/";

export const publicRequest = axios.create({
  baseURL: BASE_URL,
});

export const userRequest = axios.create({
  baseURL: BASE_URL,
});

// 添加请求拦截器,每次请求前注入最新TOKEN
userRequest.interceptors.request.use((config) => {
  const user = JSON.parse(localStorage.getItem("persist:root"))?.user;
  const currentUser = user && JSON.parse(user).currentUser;
  const token = currentUser?.accessToken;

  if (token) {
    // 修正headers拼写,正确设置请求头
    config.headers.token = `Bearer ${token}`;
  }
  return config;
});

2. 调整请求发起时机,确保TOKEN已存在

修改Order.jsx中的useEffect,先检查TOKEN是否存在,不存在则延迟重试(或结合登录状态监听):

import { userRequest } from "../../requestMethods";
import { useEffect, useState } from "react";

const Orders = () => {
  const [orders, setOrders] = useState([]);

  const getOrders = async () => {
    try {
      const res = await userRequest.get("orders");
      setOrders(res.data);
    } catch (err) {
      console.error("获取订单失败:", err);
    }
  };

  useEffect(() => {
    const checkTokenAndFetch = () => {
      const user = JSON.parse(localStorage.getItem("persist:root"))?.user;
      const currentUser = user && JSON.parse(user).currentUser;
      
      if (currentUser?.accessToken) {
        getOrders();
      } else {
        // 刚登录时可能localStorage未更新,延迟500ms重试
        setTimeout(checkTokenAndFetch, 500);
      }
    };

    checkTokenAndFetch();
  }, []);

  console.log(orders);

  return <div>{/* 订单渲染内容 */}</div>;
};

export default Orders;

3. 验证后端中间件逻辑

确保verifyToken.js中正确解析Bearer格式的TOKEN:

const jwt = require("jsonwebtoken");

const verifyToken = (req, res, next) => {
  const authHeader = req.headers.token;
  if (authHeader) {
    // 分割Bearer和token部分
    const token = authHeader.split(" ")[1];
    jwt.verify(token, process.env.JWT_SEC, (err, user) => {
      if (err) return res.status(403).json("Token无效");
      req.user = user;
      next();
    });
  } else {
    return res.status(401).json("未授权,请携带TOKEN");
  }
};

const verifyTokenAndAdmin = (req, res, next) => {
  verifyToken(req, res, () => {
    if (req.user.isAdmin) {
      next();
    } else {
      res.status(403).json("无管理员权限");
    }
  });
};

module.exports = { verifyToken, verifyTokenAndAdmin };

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:15:10