如何获取已登录用户的邮箱?基于Express+Passport的校园项目技术求助
获取已登录用户信息的解决方案
看起来你现在的核心问题是登录后无法正确获取当前用户的信息,同时代码里还有几个和数据库交互、Passport配置相关的小问题,我帮你一步步梳理修正:
核心问题:登录后用户信息的获取方式错误
你现在在/startseite路由里用req.body.email来获取用户邮箱,这是不对的——req.body只在POST请求提交表单时才有数据,登录后的用户信息Passport已经帮你存在req.user对象里了,直接用这个就行:
// 修改server.js里的startseite路由 app.get('/startseite', checkAuthenticated, (req, res) => { // 登录成功后,Passport会把用户信息挂载到req.user上 res.render('startseite.ejs', { user: req.user }); console.log(req.user); // 可以在这里打印完整的用户对象,确认数据 })
之后你在startseite.ejs里就可以直接用<%= user.email %>、<%= user.name %>来展示用户信息了。
关键修正:Passport要从数据库查询用户,而非内存数组
你现在的Passport配置里,getUserByEmail和getUserById是从内存的users数组里查的,但你的用户数据存在数据库里,这会导致登录验证和序列化/反序列化出问题,必须改成从数据库异步查询:
1. 修改server.js里的initializePassport调用
// 先确保引入db的查询方法 const { query } = require('./db'); // 替换原来的initializePassport参数 initializePassport( passport, // 从数据库按邮箱查用户(异步函数) async (email) => { const result = await query('SELECT * FROM Players WHERE email = ?', [email]); return result[0]; // 返回第一个匹配的用户(邮箱唯一) }, // 从数据库按ID查用户(异步函数) async (id) => { const result = await query('SELECT * FROM Players WHERE id = ?', [id]); return result[0]; } )
2. 修正passport-config.js里的验证逻辑
因为现在getUserByEmail是异步函数,必须加await才能拿到用户数据:
const authenticateUser = async (email, password, done) => { // 必须await异步查询的结果 const user = await getUserByEmail(email); if(user == null){ return done(null, false, {message: 'Email or password incorrect'}); } try { if(await bcrypt.compare(password, user.password)) { return done(null, user); } else { return done(null, false, {message: 'Email or password incorrect'}) } } catch(e) { return done(e) } } // 反序列化用户也要改成异步,因为getUserById现在是异步函数 passport.deserializeUser(async (id, done) => { try { const user = await getUserById(id); done(null, user); } catch(e) { done(e); } })
其他重要修正
1. 注册时的邮箱重复检查(修复语法+改用数据库查询)
你原来的循环检查有语法错误,而且用循环遍历内存数组效率极低,直接用数据库查询更可靠:
app.post('/register', checkNotAuthenticated, async (req, res, next) =>{ try { // 先查数据库,看邮箱是否已存在 const existingUser = await query('SELECT * FROM Players WHERE email = ?', [req.body.email]); if(existingUser.length > 0){ console.log(`${req.body.email} email already taken`); // 用flash消息提示用户(需要确保你已经配置了flash中间件) req.flash('error', 'This email is already registered'); return res.redirect('/register'); } const hashedPassword = await bcrypt.hash(req.body.password, 10); // 注意:如果你的Players表id是自增主键,这里不需要手动设置id,数据库会自动生成 const newUser = { name: req.body.name, email: req.body.email, password: hashedPassword } // 用参数化查询防止SQL注入,绝对不要直接拼接字符串! const sql = `INSERT INTO Players (email, name, password) VALUES (?, ?, ?)`; await connection.query(sql, [newUser.email, newUser.name, newUser.password]); console.log(`User with email: ${newUser.email} inserted`); res.redirect('/login'); } catch (err) { console.error(err); req.flash('error', 'Registration failed, please try again'); res.redirect('/register'); } })
2. 修复allPlayers函数的查询逻辑
原来的query("*")是无效的,改成正确的数据库查询:
async function allPlayers(){ try { const values = await query('SELECT * FROM Players'); // 清空数组再添加,避免重复加载 users.length = 0; values.forEach(user => users.push(user)); console.log('Loaded all users from database:', users); } catch(err) { console.error('Failed to load users:', err); } }
总结关键点
- 登录后用户信息永远从
req.user获取,这是Passport的标准用法 - Passport的用户查询函数必须和数据库交互,不能依赖内存数组(重启服务器后内存数据会丢失)
- 数据库操作一定要用参数化查询,防止SQL注入
- 所有异步操作(数据库查询、bcrypt加密)都要正确使用
await和try/catch处理异常
内容的提问来源于stack exchange,提问作者Ron M
相关产品推荐
相关产品推荐

