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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 00:57:15