JWT验证报错:Cannot read properties of undefined (reading 'id')及Token无效问题
问题分析与解决方案
核心错误点
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')。错误处理未终止流程
在jwt.verify的回调中,验证失败时你返回了错误响应,但没有终止函数执行,后续的req.user = user和next()仍会运行,导致逻辑混乱。次要问题:依赖未引入
用户更新接口中使用了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
相关产品推荐
相关产品推荐

