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

使用Express的JWT认证中间件无法从Axios GET请求的req中获取userId怎么办

问题根因

你遇到的问题是多个错误叠加导致的,逐一拆解如下:

  1. GET请求不支持携带请求体
    HTTP规范中GET请求的请求体没有定义语义,绝大多数浏览器、HTTP客户端、服务端都会主动忽略GET请求携带的body内容。同时Axios的get方法参数规则和POST不同:axios.get(url[, 配置对象]),你传入的第二个参数formData会被Axios当成配置项处理,根本不会作为请求体发送。
  2. 请求头和传输数据格式完全不匹配
    你创建了FormData对象(对应Content-Type为multipart/form-data),却手动把请求头的Content-Type设置成了application/json,就算是POST请求,服务端的express.json()中间件也完全无法解析对应内容。
  3. useCallback依赖错误
    你当前的fetchPosts的依赖数组里包含了posts,而回调内部执行了setPosts,会导致posts更新后重新生成fetchPosts触发重复请求,陷入无限循环。

修复方案

方案1:保留GET请求(推荐,查询类接口符合REST规范)

GET请求的参数应该放在URL查询串中,不需要传递body,修改代码如下:

前端修改

const fetchPosts = useCallback(() => {
  Axios.get('http://localhost:3001/api/post', {
    // 将userId放到查询参数中,Axios会自动拼接到URL后
    params: {
      userId: userId
    },
    headers: {
      "Authorization": LStoken
      // 不需要手动设置Content-Type,GET请求无body无需该字段
    }
  })
  .then((response) => {
    console.log(response)
    setPosts(response.data)
  })
// 移除依赖数组中的posts,避免无限循环
}, [LStoken, userId])

中间件修改

将原来读取req.body.userId的逻辑改为读取req.query.userId:

const jwt = require('jsonwebtoken');

module.exports = (req, res, next) => {
  try {
    const token = req.headers.authorization.split(' ')[1];
    const decodedToken = jwt.verify(token, 'RANDOM_TOKEN_SECRET');
    const userId = decodedToken.userId;
    const moderator = decodedToken.moderator
    console.log(moderator)
    // 从query中读取userId
    console.log(req.query.userId)
    if (req.query.userId && req.query.userId !== userId || req.body.moderator == false ) {
      throw 'Invalid user ID';
    } else {
      next();
    }
  } catch {
    res.status(401).json({
      error: new Error('Invalid request!')
    });
  }
};

方案2:改为POST请求(适合需要提交大量数据/文件的场景)

如果该接口需要提交其他数据(比如文件),可以改为POST请求,修改代码如下:

前端修改

const fetchPosts = useCallback(() => {
  // 不需要传文件的话完全没必要用FormData,直接传JSON对象即可
  const postData = { userId: userId };
  Axios.post('http://localhost:3001/api/post', postData, {
    headers: {
      "Authorization": LStoken
      // 不需要手动设置Content-Type,Axios会自动设为application/json
    }
  })
  .then((response) => {
    console.log(response)
    setPosts(response.data)
  })
// 移除依赖数组中的posts,避免无限循环
}, [LStoken, userId])

后端路由修改

将原来的app.get('/api/post', ...)改为app.post('/api/post', ...)即可,原来的中间件逻辑不需要改动。


内容的提问来源于stack exchange,提问作者A.Tshi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 00:06:04