NodeJS 使用Passport实现用户注册后自动登录报session序列化错误如何解决
问题原因
你的failed to serialize user into session报错由3个问题共同导致:
req.login传参错误:该方法第一个参数要求传入完整的用户对象,你传入的是邮箱密码组成的数组,serializeUser执行时读取不到user.id字段直接报错。- 异步执行顺序错误:你把
req.login放在了INSERT数据库操作的外层,INSERT是异步执行,调用req.login时很可能用户还未写入数据库。且req.login本身不会触发passport的登录校验逻辑,传入账号密码没有任何作用。 - 重复初始化passport多余:
initPassport仅需要在服务启动时调用一次,每次注册时重复调用可能导致策略重复挂载的问题。
修正方案
修改后的注册逻辑代码如下:
register(req, res, next) { const errors = validationResult(req); if (!errors.isEmpty()) { req.flash('errors', errors.array({ onlyFirstError: true })); return res.redirect('back'); } const checkEmailSQL = `SELECT email FROM users WHERE email = ${pool.escape(req.body.email)}`; pool.query(checkEmailSQL, (err, result) => { if (result.length !== 0) { req.flash('error_message', '该邮箱已被注册,请重试。'); return res.redirect('back'); } const insertSQL = 'INSERT INTO contact_app.users (username, email, password) VALUES (?, ?, ?)'; const encryptPassword = Hash.encryptPass(req.body.password); pool.query(insertSQL, [req.body.username, req.body.email, encryptPassword], (err, insertResult) => { if (err) { console.error(err); req.flash('error_message', '注册失败,请稍后重试'); return res.redirect('back'); } // 组装完整用户对象,insertResult.insertId为新用户的自增ID const newUser = { id: insertResult.insertId, username: req.body.username, email: req.body.email, password: encryptPassword }; // 传入完整用户对象完成自动登录 req.login(newUser, (err) => { if (err) { return next(err); } res.redirect('/perfil'); }); }); }); }
补充说明
如果不想手动组装用户对象,可在INSERT执行成功后,用新注册的邮箱查询数据库拿到完整用户数据再传给req.login即可,逻辑和你passport本地策略中的查询逻辑一致。
另外请删除注册逻辑中的initPassport()调用,将该方法移到服务启动入口文件中执行一次即可。
内容的提问来源于stack exchange,提问作者Álvaro
相关产品推荐
相关产品推荐

