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

Express+MongoDB项目展示用户资料时遇TypeError问题求助

解决Express.js中TypeError: Cannot read properties of undefined (reading 'passport')问题

问题场景

开发基于Express.js+MongoDB的用户资料展示项目时,访问仪表盘页面触发以下错误:

TypeError: C:\Users\go\Downloads\mongo-class\views\dashboard.ejs:117
    115|         <div class="profile">

    116|           

 >> 117|           <div><img src=<%= foundUser.passport %>  alt=<%= foundUser.fullname %>></div>

    118|           <div class="fullname"><p><%=foundUser.fullname %></p></div>

    119|           <div class="phone"><p><%= foundUser.phone %></p></div>

    120|           <div class="name"><p><%=foundUser.email %></p></div>


Cannot read properties of undefined (reading 'passport')
    at eval ("C:\\Users\\go\\Downloads\\mongo-class\\views\\dashboard.ejs":13:36)
    at dashboard (C:\Users\go\Downloads\mongo-class\node_modules\ejs\lib\ejs.js:703:17)
    at tryHandleCache (C:\Users\go\Downloads\mongo-class\node_modules\ejs\lib\ejs.js:274:36)
    at View.exports.renderFile [as engine] (C:\Users\go\Downloads\mongo-class\node_modules\ejs\lib\ejs.js:491:10)
    at View.render (C:\Users\go\Downloads\mongo-class\node_modules\express\lib\view.js:135:8)
    at tryRender (C:\Users\go\Downloads\mongo-class\node_modules\express\lib\application.js:657:10)
    at Function.render (C:\Users\go\Downloads\mongo-class\node_modules\express\lib\application.js:609:3)
    at ServerResponse.render (C:\Users\go\Downloads\mongo-class\node_modules\express\lib\response.js:1039:7)
    at C:\Users\go\Downloads\mongo-class\app.js:139:9
    at Layer.handle [as handle_request] (C:\Users\go\Downloads\mongo-class\node_modules\express\lib\router\layer.js:95:5)

错误根源分析

  1. 全局变量foundUser不可靠:用全局变量存储登录用户信息,未登录直接访问/路由时foundUser为undefined,EJS直接访问其属性触发报错;且全局变量在多用户场景下会导致数据混乱。
  2. MongoDB连接未等待完成:connectDB函数中mongoose.connect未加await,数据库未建立连接就执行查询,可能导致User.findOne返回undefined。
  3. 缺失依赖与边界处理:login路由使用bcrypt但未导入,Admin模型未引入;同时未处理用户/管理员都不存在的情况。
  4. EJS模板无防御性判断:直接假设foundUser一定存在,未做判空处理。

解决方案

1. 改用Session存储用户信息

全局变量不适合会话管理,用express-session存储用户登录状态:

  • 安装依赖:npm install express-session
  • 配置Session:
const session = require('express-session');
app.use(session({
  secret: 'your-strong-secret-key', // 替换为实际密钥
  resave: false,
  saveUninitialized: false,
  cookie: { secure: false } // 生产环境建议设为true(需HTTPS)
}));
  • 登录成功后存入Session:
if (isMatch) {
  req.session.user = foundUser;
  res.redirect('/');
}

2. 修复数据库连接逻辑

将connectDB改为异步函数,等待连接完成:

async function connectDB() {
    try{
        console.log("connection to db")
        await mongoose.connect('mongodb://127.0.0.1:27017/db'); // 添加await
        console.log("connected")
    } catch (error) {
          console.log(error)
    }
}
connectDB()

3. 完善/路由逻辑

从Session获取用户信息,未登录则重定向到登录页:

app.get('/', (req, res )=>{
  if (!req.session.user) {
    return res.redirect('/login');
  }
  res.render('dashboard.ejs', {foundUser: req.session.user})
})

4. 补充缺失依赖与边界处理

在服务端顶部导入依赖:

const bcrypt = require('bcrypt');
const Admin = require('./model/admin'); // 替换为实际Admin模型路径

处理用户/管理员都不存在的情况:

}else{
    const foundAdmin = await Admin.findOne({username:username})
    if(foundAdmin){
        // 原有管理员验证逻辑
    } else {
        req.flash('info', 'Username or Password incorrect')
        res.redirect('/login')
    }
}

5. EJS模板添加防御性判空

先判断foundUser是否存在,再访问属性:

<div class="profile">
  <% if (foundUser) { %>
    <div><img src="<%= foundUser.passport %>" alt="<%= foundUser.fullname %>"></div>
    <div class="fullname"><p><%= foundUser.fullname %></p></div>
    <div class="phone"><p><%= foundUser.phone %></p></div>
    <!-- 注意:Schema中无email字段,此处改为username -->
    <div class="name"><p><%= foundUser.username %></p></div>
  <% } else { %>
    <p>请先登录</p>
    <a href="/login">前往登录</a>
  <% } %>
</div>

修正后的完整服务端代码示例

const express = require('express')
const app = express()
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const session = require('express-session');
const User = require('./model/reguser');
const Admin = require('./model/admin'); // 替换为实际路径

// 配置Session
app.use(session({
  secret: 'your-strong-secret-key',
  resave: false,
  saveUninitialized: false,
  cookie: { secure: false }
}));

// 解析表单数据
app.use(express.urlencoded({ extended: true }));

async function connectDB() {
    try{
        console.log("connection to db")
        await mongoose.connect('mongodb://127.0.0.1:27017/db');
        console.log("connected")
    } catch (error) {
          console.log(error)
    }
}
connectDB()

app.post('/login', async (req, res)=>{
    const {username, password} = req.body
    const foundUser = await User.findOne({username:username})

    if(foundUser){
        const isMatch = await bcrypt.compare(password, foundUser.password)
        if (isMatch){
            req.session.user = foundUser;
            res.redirect('/')
        }else{
            req.flash('info', 'Username or Password incorrect')
            res.redirect('/login')
        }
    }else{
        const foundAdmin = await Admin.findOne({username:username})
        if(foundAdmin){
            const isMatch = await bcrypt.compare(password, foundAdmin.password)
            if(isMatch){
                req.session.user = foundAdmin;
                res.redirect('/admin')
            }else{
                req.flash('info', 'Username or Password incorrect')
                res.redirect('/login')
            } 
        } else {
            req.flash('info', 'Username or Password incorrect')
            res.redirect('/login')
        }
    }
})

app.get('/', (req, res )=>{
    if (!req.session.user) {
        return res.redirect('/login');
    }
    res.render('dashboard.ejs', {foundUser: req.session.user})
})

// 启动服务
app.listen(3000, () => {
  console.log('Server running on port 3000');
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:25:55