使用passport-local-mongoose开发注册登录页时触发MongooseError报错
问题描述
使用passport-local-mongoose开发注册/登录页面,注册后用户数据可正常存入MongoDB,但跳转至认证页面时触发以下错误:
MongooseError: Query.prototype.exec() no longer accepts a callback
问题代码
const bodyParser = require('body-parser'); const mongoose = require('mongoose'); const express = require('express') const ejs = require("ejs"); const session = require('express-session'); const passport = require("passport"); const passportLocalMongoose = require("passport-local-mongoose"); const app = express() app.use(bodyParser.urlencoded({ extended: true })) app.set('view engine', 'ejs'); app.use(express.static("public")); app.use(session({ secret:'the s key', resave:false, saveUninitialized:false })); app.use(passport.initialize()); app.use(passport.session()); mongoose.connect("mongodb://0.0.0.0:27017/userDB", {useNewUrlParser: true}); const userSchema = new mongoose.Schema({ username:String, password:String, tbd:String }); //hash and salt psw and save users to db userSchema.plugin(passportLocalMongoose); const User = mongoose.model('User', userSchema); passport.use(User.createStrategy()); passport.serializeUser(User.serializeUser()); passport.deserializeUser(User.deserializeUser()); app.get('/test', function(req,res){ res.render('test'); }); app.get('/login', function(req,res){ res.render('login'); }); app.get('/register',function(req,res){ res.render('register'); }); app.get('/',function(req,res){ res.redirect('login'); }); app.get("/mainpage",function(req,res){ if(req.isAuthenticated()){ console.log(req.isAuthenticated()); res.render('/mainpage'); }else{ console.log(req.isAuthenticated()); res.redirect('login'); } }); app.get('/logout',function(req,res){ req.logout(); res.redirct('/login') }) app.post('/login',function(req,res){ const user = new User({ username:req.body.username, password:req.body.psw }); req.login(user,function(err){ if (err) { console.log(err); }else{ passort.authenticate("local")(req, res, function(){ res.redirct("/mainpage") }) } }); }); app.post("/register", function(req, res){ User.register({username: req.body.username}, req.body.password, function(err, user){ if (err) { console.log(err); res.redirect("/register"); } else { passport.authenticate('local').then(()=> { res.redirect("/mainpage"); }) } }); }); app.listen(3000, function() { console.log("Server started on port 3000"); });
解决方案
核心原因
错误源于Mongoose版本兼容性问题:当前使用的Mongoose是v6+版本,该版本已移除Query.prototype.exec()的回调参数支持,仅返回Promise;而旧版本的passport-local-mongoose仍在使用回调式exec(),导致冲突。此外代码中存在拼写错误,也会阻碍功能正常运行。
修复步骤
升级passport-local-mongoose
安装适配Mongoose v6+的最新版本:npm update passport-local-mongoose修正代码拼写错误
- 将
passort.authenticate改为passport.authenticate(登录路由中) - 将所有
res.redirct改为res.redirect(登出、登录、注册路由中)
- 将
修正认证逻辑写法
注册路由中passport.authenticate的用法错误,需改用标准中间件写法;同时建议用async-await优化异步逻辑,避免回调嵌套。
修复后的完整代码
const bodyParser = require('body-parser'); const mongoose = require('mongoose'); const express = require('express') const ejs = require("ejs"); const session = require('express-session'); const passport = require("passport"); const passportLocalMongoose = require("passport-local-mongoose"); const app = express() app.use(bodyParser.urlencoded({ extended: true })) app.set('view engine', 'ejs'); app.use(express.static("public")); app.use(session({ secret:'the s key', resave:false, saveUninitialized:false })); app.use(passport.initialize()); app.use(passport.session()); // 添加MongoDB连接错误处理 mongoose.connect("mongodb://0.0.0.0:27017/userDB", {useNewUrlParser: true, useUnifiedTopology: true}) .then(() => console.log("Connected to MongoDB")) .catch(err => console.log(err)); const userSchema = new mongoose.Schema({ username:String, password:String, tbd:String }); userSchema.plugin(passportLocalMongoose); const User = mongoose.model('User', userSchema); passport.use(User.createStrategy()); passport.serializeUser(User.serializeUser()); passport.deserializeUser(User.deserializeUser()); app.get('/test', function(req,res){ res.render('test'); }); app.get('/login', function(req,res){ res.render('login'); }); app.get('/register',function(req,res){ res.render('register'); }); app.get('/',function(req,res){ res.redirect('login'); }); app.get("/mainpage",function(req,res){ if(req.isAuthenticated()){ console.log(req.isAuthenticated()); // 修正:res.render参数为模板文件名,不需要加/ res.render('mainpage'); }else{ console.log(req.isAuthenticated()); res.redirect('login'); } }); app.get('/logout', function(req, res) { // 修正:req.logout需传入回调处理错误 req.logout(function(err) { if (err) { return console.log(err); } res.redirect('/login'); }); }); app.post('/login', function(req, res) { const user = new User({ username: req.body.username, password: req.body.psw }); req.login(user, function(err) { if (err) { console.log(err); return res.redirect('/login'); } passport.authenticate("local")(req, res, function() { res.redirect("/mainpage"); }); }); }); app.post("/register", async function(req, res) { try { const user = await User.register({ username: req.body.username }, req.body.password); passport.authenticate('local')(req, res, function() { res.redirect("/mainpage"); }); } catch (err) { console.log(err); res.redirect("/register"); } }); app.listen(3000, function() { console.log("Server started on port 3000"); });
内容的提问来源于stack exchange,提问作者Swnoob
相关产品推荐
相关产品推荐

