Node中使用Passport实现登录功能时报错无法正常处理登录请求
问题排查与解决方案
MissingUsernameError 是 passport-local-mongoose 抛出的错误,核心原因是你使用邮箱作为登录账号,但没有在插件配置中同步指定用户名字段为email,导致插件默认读取username字段,找不到就抛出该错误。同时你的自定义登录校验逻辑存在密码未校验的安全漏洞,具体修复方案如下:
问题清单
- 未在Users模型的
passport-local-mongoose插件注册逻辑中指定usernameField: 'email',和你LocalStrategy的配置不匹配 - 自定义LocalStrategy中仅校验了用户是否存在,完全没有校验密码正确性,存在严重逻辑漏洞
- 你注释掉了Users模型引入代码,运行时会找不到Users对象报错(如果实际运行时取消了注释可忽略该点)
修复步骤
步骤1:调整Users模型配置
打开你的./models/Users.js文件,修改passport-local-mongoose插件注册逻辑,指定用户名字段为email:
const mongoose = require('mongoose'); const passportLocalMongoose = require('passport-local-mongoose'); const userSchema = new mongoose.Schema({ // 保留你原有其他字段配置 email: { type: String, required: true, unique: true } }); // 关键配置:指定用户名字段为email userSchema.plugin(passportLocalMongoose, { usernameField: 'email' }); module.exports = mongoose.model('Users', userSchema);
步骤2:简化passport配置(推荐)
你使用passport-local-mongoose的情况下,不需要自定义LocalStrategy,直接使用框架内置的校验逻辑即可,修改你的服务启动代码:
var app = express(); app.set("view engine", "ejs"); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static('public')); app.use(require("express-session")({ secret: "Rusty is a dog", resave: false, saveUninitialized: false })); // 先取消注释引入Users模型 const Users = require('./models/Users'); app.use(passport.initialize()); app.use(passport.session()); // 直接使用框架内置的策略,自动适配你模型中配置的email字段 passport.use(Users.createStrategy()); passport.serializeUser(Users.serializeUser()); passport.deserializeUser(Users.deserializeUser()); // 登录路由保持原有配置即可 app.post("/login", passport.authenticate("local", { successRedirect: "/shop", failureRedirect: "/login", }), function (req, res) { res.redirect('/shop') } );
保留自定义LocalStrategy的可选方案
如果你一定要保留自己写的LocalStrategy逻辑,需要补充密码校验步骤,修改LocalStrategy代码如下:
passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' }, (email, password, done) => { User.findOne({ email: email }, (error, user) => { if (error) { console.log(error) return done(error); } if (!user) { console.log("User not found") return done(null, false, { message: 'Username or password incorrect' }); } // 新增:调用模型内置的authenticate方法校验密码 user.authenticate(password, (err, validUser, passErr) => { if (err) return done(err); if (passErr) return done(null, false, { message: '账号或密码错误' }); return done(null, validUser); }); }); } ));
额外校验项
确认你的前端登录表单提交的字段名和配置一致,分别为email和password,如果字段名不匹配也会触发该错误。
内容的提问来源于stack exchange,提问作者Thiluxan
相关产品推荐
相关产品推荐

