使用Passport Local策略登录异常:findByUsername始终返回undefined
问题诊断与修复方案
你的登录POST路由失效,核心问题出在异步逻辑处理错误和函数调用方式错误,以下是具体问题和修复步骤:
1. findByUsername 函数无法返回用户数据
原函数使用回调式的pool.query,但没有将异步查询的结果通过Promise返回,直接调用会得到undefined。修复方式是把函数改成Promise风格:
const findByUsername = (name) => { return new Promise((resolve, reject) => { pool.query( "SELECT * FROM users WHERE username = $1", [name], (error, results) => { if (error) { return reject(error); } // 返回第一个匹配的用户(用户名唯一的话) resolve(results.rows[0]); } ); }); };
2. Passport Local策略的逻辑错误
原策略里存在两个致命问题:
- 没有调用
findByUsername函数(只是赋值了函数本身,没传用户名参数) bcrypt.compare是异步方法,不能同步赋值判断
修复后的策略代码(使用async/await处理异步):
passport.use( new LocalStrategy(async (username, password, done) => { try { // 调用函数并传入用户名参数 const user = await du.findByUsername(username); if (!user) { console.log("用户不存在"); return done(null, false, { message: "用户不存在" }); } // 异步验证密码 const match = await bcrypt.compare(password, user.pword); if (!match) { console.log("密码错误"); return done(null, false, { message: "密码错误" }); } console.log("登录成功"); return done(null, user); } catch (err) { return done(err); } }) );
3. 路由配置的潜在冲突
原POST路由同时挂载了/users/login和/users/:id,当请求/users/login时,可能会被:id的路由规则匹配(把login当成id参数),导致逻辑混乱。建议分开定义路由:
// 登录路由 router.post( "/users/login", passport.authenticate("local", { failureRedirect: "/users/login", }), (req, res) => { // 登录成功后重定向到产品列表,若db.getAllProducts是标准中间件可直接替换此回调 res.redirect("/products"); } ); // 其他用户相关POST路由(比如更新用户) router.post("/users/:id", (req, res) => { // 你的业务逻辑 }); module.exports = router;
额外注意事项
- 确保
passport已正确配置serializeUser和deserializeUser(登出功能依赖此配置) - 数据库中存储的密码必须是
bcrypt.hash生成的哈希值,不能是明文
内容的提问来源于stack exchange,提问作者Blakjay116
相关产品推荐
相关产品推荐

