Mongodb TypeError:[函数]不是Passport本地策略中的函数

Mongodb TypeError:[函数]不是Passport本地策略中的函数,mongodb,express,passport.js,Mongodb,Express,Passport.js,我正在尝试使用Passport.js在本地对用户进行身份验证,同时不保留会话并使用我自己的JWToken 我遵循本教程: 同时阅读Passport.js文档。我不知道出了什么问题,但passport似乎没有注意到某些函数确实是函数 我有一个加载函数,可以根据特定条件(用户可以使用电子邮件或电话号码登录)从DB(mongo)中选择一个用户 我正在呼叫passport.authenticate在我的路线中: // Controllers // const Users = require('../.

我正在尝试使用Passport.js在本地对用户进行身份验证,同时不保留会话并使用我自己的JWToken

我遵循本教程:

同时阅读Passport.js文档。我不知道出了什么问题,但passport似乎没有注意到某些函数确实是函数

我有一个加载函数,可以根据特定条件(用户可以使用电子邮件或电话号码登录)从DB(mongo)中选择一个用户

我正在呼叫passport.authenticate在我的路线中:

// Controllers //
const Users = require('../../app/controllers/users');  
...
...  
app.post('/api/login', passport.authenticate('local', { failureRedirect: '/api/login' }), Users.login);
以下是我的本地策略:

const mongoose = require('mongoose');
const User = mongoose.model('User');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(
  {
  usernameField: 'email',
  phoneField: 'phone',
  passwordField: 'password',
  session: false
  }, 

  function(email, phone, password) {//cb == callback
    const options = {
      criteria: { email: email, phone: phone },
      select: 'name username email hashed_password salt'    
    };

    User.load(options, function(err, user) {

      if (err || !user){
        return res.status(400).json({
          type: 'failure',
          message: "User creation failed",  
          data: [err]
        });
      };

      if (!user.authenticate(password)) {
        return res.status(400).json({
          type: 'failure',
          message: "User creation failed",  
          data: [err]
        });
      };

      req.login(user, {session: false}, (err) => {
         if (err) {
             res.send(err);
         }

         // generate a signed son web token with the contents of user object and return it in the response
         const token = jwt.sign(user.id, 'your_jwt_secret');
         return res.json({user, token});
      });
    });
  }
));
我得到以下错误:

TypeError: res.status is not a function
在试图从passport和Response取回东西之前。我试图用cb(callback)来做这件事,就像在教程中做的那样,但是我一直得到相同的错误


提前感谢您的帮助

您在如何实施Passport的本地策略方面存在一些问题,这些问题会造成问题

当Passport的本地startegy只接受一个字段时,您尝试使用两个字段作为用户名。(见:)

如果您想将两者都用作用户名,您可能需要考虑创建自己的自定义策略。这将更加深入,但您可以从Passport Github页面()开始学习

第二个问题是,您正试图让Passport在本地策略中发送响应,而这并不是它想要做的。相反,您应该将错误和返回值传递给Passport的
done()
函数,该函数将相应地处理它们

以下是您的本地策略的示例:

passport.use(
    new LocalStrategy(async (email, phone, password, done) => {
        const options = {
            criteria: { email, phone },
            select: 'name username email hashed_password salt',
        };

        try {
            const user = await User.load(options);

            /**
             * If null is returned meaning there was no user found, send the done call
             * with the false flag. This tells passport to redirect to the failure URL.
             */
            if (!user) {
                return done(null, false);
            }

            /**
             * If the user's password is incorrect, also return the done function with the false
             * flag. This tells passport to redirect to the failure URL.
             */
            if (!user.authenticate(password)) {
                return done(null, false);
            }

            /**
             * If a user is found and their password is verified, send the user object to
             * the done function. This will tell Passport to call the next middelware attaching
             * the user object.
             */
            return done(null, user);
        } catch (err) {
            /**
             * If there is an error with the DB call, return generic message
             * for security purposes.
             */
            return done('There was an internal server error.');
        }
    })
);
load: options => {
    return new Promise(async (resolve, reject) => {
        options.select = options.select || 'email phone';
        try {
            const user = await this.findOne(options.criteria)
                .select(options.select)
                .exec();

            resolve(user);
        } catch (err) {
            reject(err);
        }
    });
};
还有一个加载函数的示例:

passport.use(
    new LocalStrategy(async (email, phone, password, done) => {
        const options = {
            criteria: { email, phone },
            select: 'name username email hashed_password salt',
        };

        try {
            const user = await User.load(options);

            /**
             * If null is returned meaning there was no user found, send the done call
             * with the false flag. This tells passport to redirect to the failure URL.
             */
            if (!user) {
                return done(null, false);
            }

            /**
             * If the user's password is incorrect, also return the done function with the false
             * flag. This tells passport to redirect to the failure URL.
             */
            if (!user.authenticate(password)) {
                return done(null, false);
            }

            /**
             * If a user is found and their password is verified, send the user object to
             * the done function. This will tell Passport to call the next middelware attaching
             * the user object.
             */
            return done(null, user);
        } catch (err) {
            /**
             * If there is an error with the DB call, return generic message
             * for security purposes.
             */
            return done('There was an internal server error.');
        }
    })
);
load: options => {
    return new Promise(async (resolve, reject) => {
        options.select = options.select || 'email phone';
        try {
            const user = await this.findOne(options.criteria)
                .select(options.select)
                .exec();

            resolve(user);
        } catch (err) {
            reject(err);
        }
    });
};
作为一般的最佳实践,我将您的回调更改为更新的promises()方法

这应该按照您打算使用Passport的方式进行