开发verifyTokenAdmin中间件遇TypeError:无法读取isAdmin属性
解决JWT鉴权中间件的TypeError: Cannot read properties of undefined (reading 'isAdmin')错误
问题原因
你遇到的错误核心是verifyAdmin中间件里的req.Users完全未定义——你的verifyToken中间件只从JWT里提取了用户ID并存到req.userId,但没有从数据库查询用户信息,也没有把用户对象挂载到请求对象上,自然无法读取isAdmin属性。
解决方案
有两种可行的修复思路,根据业务需求选择:
方案1:验证Token后查询数据库获取用户信息
这种方式更安全,即使用户的isAdmin权限在Token签发后被修改,也能实时生效。
- 修改
verifyToken中间件:引入User模型,验证Token后查询用户并挂载到req.user上(需改为异步函数):
const jwt = require('jsonwebtoken'); const User = require('../models/User'); // 路径根据项目结构调整 const verifyToken = async (req, res, next) => { const { authorization } = req.headers; if (!authorization) { return res.status(401).json('无效的授权信息') }; // 优化Token提取逻辑:拆分Bearer和Token部分 const token = authorization.split(' ')[1]; if (!token) { return res.status(401).json('无效的Token格式'); } try { const secret = process.env.JWT_SECRET; const data = jwt.verify(token, secret); const user = await User.findByPk(data.id); if (!user) { return res.status(404).json('用户不存在'); } req.user = user; // 将用户对象挂载到请求上 return next(); } catch (err) { return res.status(400).json('Token验证失败'); } }; const verifyAdmin = (req, res, next) => { // 直接访问req.user的isAdmin属性 if (req.user.isAdmin) { next(); } else { return res.status(403).json("你无权执行此操作!"); } } module.exports = { verifyToken, verifyAdmin, };
- 路由无需修改:中间件执行顺序保持
verifyToken→verifyAdmin即可。
方案2:生成Token时将isAdmin写入Payload
这种方式无需查询数据库,性能更高,但用户权限修改后需重新签发Token才会生效。
- 生成Token时添加
isAdmin字段(在用户创建或登录逻辑中):
// 示例:登录成功后生成Token const token = jwt.sign( { id: user.id, isAdmin: user.isAdmin }, // 将isAdmin写入Payload process.env.JWT_SECRET, { expiresIn: '24h' } );
- 修改中间件:直接从Token解析结果中提取
isAdmin:
const jwt = require('jsonwebtoken'); const verifyToken = (req, res, next) => { const { authorization } = req.headers; if (!authorization) { return res.status(401).json('无效的授权信息') }; const token = authorization.split(' ')[1]; if (!token) { return res.status(401).json('无效的Token格式'); } try { const secret = process.env.JWT_SECRET; const { id, isAdmin } = jwt.verify(token, secret); req.userId = id; req.isAdmin = isAdmin; // 将isAdmin挂载到请求上 return next(); } catch (err) { return res.status(400).json('Token验证失败'); } }; const verifyAdmin = (req, res, next) => { if (req.isAdmin) { next(); } else { return res.status(403).json("你无权执行此操作!"); } } module.exports = { verifyToken, verifyAdmin, };
额外注意事项
- 给User模型的
isAdmin字段添加默认值,避免null值:
// 在User模型的init方法中修改 isAdmin: { type: DataTypes.BOOLEAN, defaultValue: false // 添加默认值 }
- 用
split(' ')[1]提取Token比replace更可靠,避免因空格数量不一致导致的错误。
内容的提问来源于stack exchange,提问作者Routfin
相关产品推荐
相关产品推荐

