Express中passport.authenticate无响应且日志顺序异常求助
Express + Passport 登录认证无响应及日志顺序异常问题解决
问题概述
使用Express、Passport和PostgreSQL实现账号创建与登录功能,数据库操作正常,但执行passport.authenticate时无任何响应,相关打印语句未输出;同时日志顺序出现颠倒:
Logging user in New user added
相关代码
index.js 核心片段
const express = require("express"); const bodyParser = require("body-parser"); const session = require("express-session"); const passport = require("passport"); const LocalStrategy = require("passport-local").Strategy; const bcrypt = require("bcrypt"); const db = require("./dbManager.js") const app = express(); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(__dirname + "/Public")); app.use(session({ secret: "example", saveUninitialized: true, resave: true })); app.use(passport.initialize()); app.use(passport.session()); // Passport本地策略配置 passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' }, function (email, password, done) { console.log("Logging in ", email); db.findUser(email).then(function (row) { if (!row) { return done(null, false, "Sorry that user doesn't exist"); } else { bcrypt.compare(password, row.password, function (ex, result) { if (result == true) { done(null, row.id); } else { return done(ex, false, "Incorrect password"); } }) } }).catch(function (ex) { console.error(ex); return done(ex, false); }); })); passport.serializeUser(function (user, done) { console.log(user, done); done(null, user.id); }); passport.deserializeUser(function (id, done) { db.deserializeUser(id).then(function (row) { console.log("User found id is:", row.id); done(null, row.id) }).catch(function (ex) { console.error(ex); }) }); // 登录路由 app.post("/logIn", function (req, res) { console.log("Logging user in"); passport.authenticate("local", function (ex, user, info) { console.log("Authentication"); if (ex) { console.error(ex); res.status(403).send(ex); } else if (!user) { console.log(info); res.status(400).send(info); } else { req.logIn(user, function (ex) { if (ex) { console.error(ex); res.status(400).send(ex); } else { console.log("User now authenticated"); res.status(200).send("Success"); } }) } }); }); // 账号创建路由 app.post("/createAccount", function (req, res) { const email = req.body.email; const password = req.body.password; bcrypt.hash(password, 10, function (ex, hashedPassword) { if (ex != null) { console.log(ex); } db.addUser(email, hashedPassword).then(function () { console.log("New user added"); res.status(204).send("user added"); }).catch(function (ex) { console.error(ex); res.status(403).send(ex); }); }); }); app.listen(3000, function () { console.log('Server running on port 3000'); });
createAccount.js 前端脚本
$("#submitBtn").click(function() { body= { email:$("#email")[0].value, password:$("#password")[0].value }; $.post("/createAccount",body).done(accountCreated(body)).fail(accountNotCreated); }); function accountCreated(body) { console.log("User Added"); console.log(body.email); $.post("/logIn",body).done(function() { console.log("You are now logged in"); window.location.replace("/"); }).fail(function(ex) { console.error(ex); }); } function accountNotCreated(ex) { console.error(ex); }
问题原因及修复方案
1. passport.authenticate无响应的核心原因
在/logIn的POST路由中,调用passport.authenticate时没有触发其执行。passport.authenticate返回的是一个中间件函数,需要手动传入req和res参数才能运行。
修复代码:
修改/logIn路由处理函数,在passport.authenticate后追加(req, res):
app.post("/logIn", function (req, res) { console.log("Logging user in"); passport.authenticate("local", function (ex, user, info) { console.log("Authentication"); if (ex) { console.error(ex); return res.status(403).send(ex); } else if (!user) { console.log(info); return res.status(400).send(info); } else { req.logIn(user, function (ex) { if (ex) { console.error(ex); return res.status(400).send(ex); } else { console.log("User now authenticated"); return res.status(200).send("Success"); } }) } })(req, res); // 关键:手动触发认证函数 });
2. 日志顺序颠倒的原因
- 前端脚本中,
$.post("/createAccount").done(accountCreated(body))是立即执行accountCreated,而非等待请求完成后执行。这导致登录请求在账号创建完成前就发送到服务器,服务器先打印Logging user in,之后账号创建的异步操作完成才打印New user added。 - 后端
bcrypt.hash是异步操作,账号创建的日志输出晚于登录请求的日志。
修复代码:
修改前端done回调的写法,传递函数引用而非立即执行:
// 原代码 $.post("/createAccount",body).done(accountCreated(body)).fail(accountNotCreated); // 修改为: $.post("/createAccount",body).done(function() { accountCreated(body); }).fail(accountNotCreated); // 或使用bind简化 $.post("/createAccount",body).done(accountCreated.bind(null, body)).fail(accountNotCreated);
3. Passport序列化的潜在问题
在passport.serializeUser中,LocalStrategy传递的user是row.id(字符串/数字类型),而非用户对象,所以user.id会报错。直接使用user即可:
passport.serializeUser(function (user, done) { console.log(user); done(null, user); // user已经是用户ID });
验证修复效果
修复后,日志顺序会变为:
New user added Logging user in Authentication User now authenticated
同时passport.authenticate的回调会正常执行,登录认证流程恢复正常。
内容的提问来源于stack exchange,提问作者Paul Geoghegan
相关产品推荐
相关产品推荐

