Express报错:Cannot read properties of null (reading 'role')
问题根因
报错TypeError: Cannot read properties of null (reading 'role')触发位置在customRole权限校验中间件,执行到读取req.user.role逻辑时,req.user的值为null,说明前置的isLoggedIn登录鉴权中间件没有正确把有效登录用户信息挂载到req对象上,就直接放行请求到了下一个中间件。
常见触发场景:
- 请求未携带有效登录token,
isLoggedIn逻辑未做拦截直接放行,没有给req.user赋值 - token解析成功,但根据token里的用户id查库时,对应用户已被删除,查询返回
null,未做拦截就把null赋值给了req.user isLoggedIn的异常捕获逻辑有问题,jwt解析、数据库查询报错时没有抛出401错误,直接放行到后续中间件- 测试请求时漏传登录凭证,导致
isLoggedIn拿不到用户信息
修复方案
- 修复
isLoggedIn中间件逻辑,确保只有拿到有效登录用户数据时才挂载到req.user并放行,所有鉴权失败场景直接返回错误拦截请求,参考实现:
const jwt = require('jsonwebtoken'); // 其他依赖按项目实际引入 exports.isLoggedIn = BigPromise(async(req, res, next) => { // 从cookie或请求头取token,适配你项目的token存储逻辑 const token = req.cookies?.token || req.header("Authorization")?.replace("Bearer ", ""); if (!token) { return next(new CustomError('请先登录后再访问', 401)); } const decodedToken = jwt.verify(token, process.env.JWT_SECRET); const loginUser = await User.findById(decodedToken.id); // 校验用户是否真实存在 if (!loginUser) { return next(new CustomError('登录账号不存在,请重新登录', 401)); } // 确认拿到有效用户对象再挂载 req.user = loginUser; next(); });
- 给
customRole中间件增加兜底校验,避免req.user为空时直接读取属性抛出500错误,优化后代码:
exports.customRole = (...roles) => { return(req, res, next) => { // 兜底校验登录用户信息是否存在 if (!req.user) { return next(new CustomError('未获取到登录身份信息', 401)); } if (!roles.includes(req.user.role)) { return next(new CustomError('You are not allowed for this resource', 403)) } next() } }
- 接口测试时确认使用admin账号登录生成的有效token,将token正确放在请求cookie或
Authorization请求头中再发起请求,即可正常访问管理员接口。
内容的提问来源于stack exchange,提问作者Aashiq Shajahan
相关产品推荐
相关产品推荐

