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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 03:18:24