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

JWT验证报错:Cannot read properties of undefined (reading 'id')及Token无效问题

问题分析与解决方案

核心错误点

  1. Token分割逻辑错误
    你在verifyToken中间件里用authHeader.split("")拆分请求头,这会把字符串按单个字符拆分。但标准JWT请求头格式是Bearer <token>,需要用空格分割。错误的分割导致拿到的不是有效Token,触发jwt.verify验证失败,返回"token not valid";同时req.user未被正确赋值,后续verifyTokenAndAuthorization里访问req.user.id就会抛出Cannot read properties of undefined (reading 'id')。

  2. 错误处理未终止流程
    在jwt.verify的回调中,验证失败时你返回了错误响应,但没有终止函数执行,后续的req.user = user和next()仍会运行,导致逻辑混乱。

  3. 次要问题:依赖未引入
    用户更新接口中使用了CryptoJS但未引入模块,会导致额外报错,需要补充引入。

修正后的代码

验证Token中间件(verifyToken.js)

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 is not valid!");
      req.user = user;
      next();
    });
  } else {
    return res.status(401).json("You are not authenticated!");
  }
};

const verifyTokenAndAuthorization = (req, res, next) => {
  verifyToken(req, res, () => {
    // 先判断req.user是否存在,避免未定义报错
    if (!req.user) {
      return res.status(403).json("Token verification failed!");
    }
    if (req.user.id === req.params.id || req.user.isAdmin) {
      next();
    } else {
      res.status(403).json("You are not allowed to do that!");
    }
  });
};

module.exports = { verifyToken, verifyTokenAndAuthorization };

用户更新接口(user.js)

const User = require("../models/User.js");
const { verifyTokenAndAuthorization } = require("./verifyToken.js");
// 补充引入CryptoJS模块
const CryptoJS = require("crypto-js");
const router = require("express").Router();

//UPDATE
router.put("/:id", verifyTokenAndAuthorization, async (req, res) => {
  if (req.body.password) {
    req.body.password = CryptoJS.AES.encrypt(
      req.body.password,
      process.env.PASS_SEC
    ).toString();
  }
  try {
    const updatedUser = await User.findByIdAndUpdate(
      req.params.id,
      { $set: req.body },
      { new: true }
    );
    res.status(200).json(updatedUser);
  } catch (err) {
    res.status(500).json(err);
  }
});

module.exports = router;

额外检查事项

  • 确保Postman请求头的token字段格式为Bearer <你的JWT Token>,若前端直接传Token字符串,需调整中间件的分割逻辑(推荐遵循Bearer标准格式)。
  • 确认process.env.JWT_SEC和process.env.PASS_SEC已正确配置,无拼写错误或环境变量未加载的情况。
  • 生成JWT时,确保Payload中包含id和isAdmin字段,否则req.user.id或req.user.isAdmin仍会报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:15:43