如何使用 passport 和 express 显示自定义错误消息

How to show custom error messages using passport and express

我在注册用户的时候检查邮箱是否已经存在。如果用户已经存在,我将传递错误消息 "email already exists"。但在前端它显示 "Unauthorized" 错误 401。我想将我从后端传递给前端的错误消息传递给它,但它传递了默认消息。下面是我如何检查用户是否已经存在并发送错误消息,

exports.register = new LocalStrategy({
    usernameField: 'email',
    passReqToCallback: true
}, function(req, email, password, done,res) {
    var newUser = new User({
        email: email,
        password: password,
        name: req.body.fname
    });
    var searchUser = {
        email: email
    };
    User.findOne(searchUser, function(err, user) {
        if (err) return done(err);
        console.log("err "+err);

        if (user) {
            return done(null, false, {
                message: "email already exists"
            });
        }
        newUser.save(function(err) {
        console.log("newUser "+newUser);
            done(null, newUser);
        })
    });
});

我使用护照进行身份验证,

authRouter.post('/signup', passport.authenticate('local-register'),function(req, res) {
    createSendToken(req.user, res);
});

错误信息不是我传给前端的。它显示未经授权的错误,这是默认错误。当我在前端的控制台中打印错误消息时,它显示,

Object {data: "Unauthorized", status: 401, config: Object, statusText: "Unauthorized"}

你没有说你想要在前端输出什么,但我猜你想让 data 成为你在 LocalStrategy 中设置的 message .

这是一种方法:

authRouter.post('/signup', function(req, res, next) {
  passport.authenticate('local-register', function(err, user, info) {
    if (err) { return next(err); }
    if (!user) { 
        res.status(401);
        res.end(info.message);
        return;
    }
    createSendToken(req.user, res);
  })(req, res, next);
});

如果您使用的是 passReqToCallback = true 那么您可以像这样发送它

if (!isMatch) { return done({ message: 'Incorrect password' }); }

您可以在 passport 中利用 passReqToCallback: true

With this option enabled, req will be passed as the first argument to the verify callback.

也利用 flash messages.

这是您如何使用它的基本示例,

// your strategy
passport.use(new LocalStrategy({
    passReqToCallback: true
  },
    (req, username, password, done) => {
      User.findOne({ username: username }, (err, user) => {
        if (err) done(err)
        if (!user) {
          console.log('user does not exists')
          return done(null, false, req.flash('message', 'User does not exist' ))
        } else {
          console.log('user exists')
          return done(null, user, req.flash('message', 'User exist'))
        }
      })
    }
  ))

// your GET login
router.get("/login", (req, res) => {
  var message = req.flash('message')
  res.render("pages/login", { message })
})

如其他答案中所述,您可以手动检查 info 参数,然后 return 您自己的消息:

// ❌ MESSY ❌
authRouter.post('/signup', function(req, res, next) {
    passport.authenticate('local-register', function(err, user, info) {
        if(info.name === 'UserExistsError' ) {
            return done(null, false, {
                message: "Email already exists"
            });
        } else if (info.name === 'IncorrectUsernameError') {
          return done(null, false, {
              message: "Email does not exist"
          });
        } else if(....

但是 MUCH 更简洁的方法是在创建 Account Mongoose 模型时指定自定义错误消息:

var Account = new Schema({
    ...
});

var options = {
    errorMessages: {
        UserExistsError: 'Email already exists',
        IncorrectUsernameError: 'Email does not exist',
        IncorrectPasswordError: ...
    }
};

Account.plugin(passportLocalMongoose, options);

然后在您的注册路径中,您可以简单地 return 将 info.message 发送给用户。

// ✨ CLEAN ✨
authRouter.post('/signup', function(req, res, next) {
    passport.authenticate('local-register', function(err, user, info) {
        return done(null, false, {
            message: info.message
        });
    });
});