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

Express中间件解构req.user报TypeError,全局传递用户Profile至Pug遇阻

问题分析与解决方案

错误根源

你的问题核心在于全局中间件的执行时机与路由内的认证保障差异:

  • 你的/user路由搭配了secured()中间件,这个中间件的作用应该是强制校验用户登录状态,只有当用户成功认证后,req.user才会被正确赋值,所以在路由处理函数里解构req.user不会出错。
  • 但全局的userInViews()中间件是在所有路由之前执行的,包括无需登录的公共路由(比如首页、登录页)。此时用户未登录,req.user是undefined,直接解构自然会抛出Cannot destructure property '_raw' of 'undefined'的错误。

另外你提到直接赋值req.user也无效,本质是因为未登录时req.user本身就是undefined,赋值给res.locals后也只是传递了一个无效值,无法解决根本问题。


解决方案

方案1:在中间件中增加登录状态判断

修改全局中间件,先通过req.isAuthenticated()校验用户是否登录,仅当用户已认证时才处理req.user,否则给userProfile设置默认值:

module.exports = function () {
  return function (req, res, next) {
    // 初始化默认值,避免未登录时出现异常
    let userProfile = null;
    
    // 仅当用户已认证且req.user存在时,才解构处理
    if (req.isAuthenticated() && req.user) {
      const { _raw, _json, ...profile } = req.user;
      userProfile = JSON.stringify(profile, null, 2);
    }

    // 不要直接覆盖res.locals,用展开运算符保留原有中间件的属性
    res.locals = {
      ...res.locals,
      userProfile,
      token: '1234',
      isAuthenticated: req.isAuthenticated(),
    };
    next();
  };
};

方案2:调整中间件挂载顺序(可选)

如果你的项目使用了全局认证中间件(比如Passport的passport.initialize()和passport.session()),需要确保userInViews()挂载在这些认证中间件之后,这样req.user才能被正确初始化:

// app.js 挂载顺序调整示例
app.use(express.json());
// 先挂载认证相关中间件
app.use(passport.initialize());
app.use(passport.session());
// 再挂载你的全局用户信息中间件
app.use(userInViews());
// 最后挂载各类路由
app.use('/user', userRouter);
// ...其他路由

补充说明

  • 避免直接覆盖res.locals:如果直接赋值res.locals = {...},会清除其他中间件(比如Express内置或第三方中间件)设置的locals属性,用...res.locals可以保留原有属性并合并你的自定义内容。
  • 测试验证:修改后,访问未登录的公共页面时中间件不会报错,userProfile为null;登录后任意页面的res.locals.userProfile都会正确传递处理后的用户信息,导航栏可以正常渲染统计数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:13:17