【问题标题】:TypeError: done is not a function类型错误:完成不是函数
【发布时间】:2017-10-21 13:10:21
【问题描述】:

我正在使用 passport.js 来验证和处理我的项目中的会话。

我使用电子邮件从护照进行身份验证,但是当在验证时调用 done 时,我得到错误 done不是函数。

at Promise.<anonymous> (/Users/sultan/Desktop/too2/controllers/users.js:39:28)
at Promise.<anonymous> (/Users/sultan/Desktop/too2/node_modules/mongoose/lib/promise.js:120:8) 

代码

  // LOCAL LOGIN =============================================================
passport.use('local-login', new LocalStrategy({
    usernameField : 'email',
    passwordField : 'password'
    //passReqToCallback : true // allows us to pass in the req from our route (lets us check if a user is logged in or not)
},
function( email, password, done) {
    if (email)
        email = email.toString().toLowerCase();

    // asynchronous
    process.nextTick(function() {
        User.findOne({ email:  email }, function(err, user) {
            // if there are any errors, return the error
            if (err)
                return done(err);

            // if no user is found, return the message
            if (!user)
        //(/Users/sultan/Desktop/too2/controllers/users.js:39:28)
                return done(null, false, {message: 'No user found.'});

            if (!user.validPassword(password))
                return done(null, false, {message: 'Oops! Wrong Password'});

            // all is well, return user
            else
                return done(null, user);
        });
    });

}));

此错误的原因是什么,我该如何解决?

【问题讨论】:

  • 您不能将done 声明为函数...
  • 如何不将“完成”声明为函数

标签: javascript node.js authentication passport.js


【解决方案1】:

我目前正在开发一个需要用户身份验证的 node.js 项目。下面是我的 passport.js 文件中的代码。它应该适合你。如果您不想使用节点包connect-flash,可以将req.flash 替换为{message:...}

 var bCrypt = require('bcrypt-nodejs');
 var db = require("../models");
 module.exports = function(passport) {
   var user = db.User;
   var User = user;
   var LocalStrategy = require('passport-local').Strategy;


   passport.serializeUser(function(user, done) {
     done(null, user.id);
   });


   // used to deserialize the user
   passport.deserializeUser(function(id, done) {
     User.findById(id).then(function(user) {
       if (user) {
         done(null, user.get());
       } else {
         done(user.errors, null);
       }
     });

   });


   passport.use('local-signup', new LocalStrategy(

     {
       usernameField: 'email',
       passwordField: 'password',
       passReqToCallback: true // allows us to pass back the entire request to the callback
     },

     function(req, email, password, done) {


       var generateHash = function(password) {
         return bCrypt.hashSync(password, bCrypt.genSaltSync(8), null);
       };

       User.findOne({
         where: {
           email: email
         }
       }).then(function(user) {

         if (user) {
           return done(null, false, req.flash('signupMessage', 'That email is already taken'));

         } else {
           var userPassword = generateHash(password);
           var data = {
             email: email,
             password: userPassword,
             firstname: req.body.firstname,
             lastname: req.body.lastname
           };


           User.create(data).then(function(newUser, created) {
             if (!newUser) {
               return done(null, false, req.flash('userExist', 'You are already registered. Please sign in!'));
             }

             if (newUser) {
               return done(null, newUser, req.flash('userCreated', 'You are now registered and logged in!'));
             }

           });
         }

       });

     }

   ));

   //LOCAL SIGNIN
   passport.use('local-signin', new LocalStrategy({
       // by default, local strategy uses username and password, we will override with email
       usernameField: 'email',
       passwordField: 'password',
       passReqToCallback: true // allows us to pass back the entire request to the callback
     },

     function(req, email, password, done) {

       var User = user;

       var isValidPassword = function(userpass, password) {
         return bCrypt.compareSync(password, userpass);
       }

       User.findOne({
         where: {
           email: email
         }
       }).then(function(user) {

         if (!user) {
           return done(null, false, req.flash('signinError', 'Email does not exist'));
         }

         if (!isValidPassword(user.password, password)) {

           return done(null, false, req.flash('passwordError', 'Incorrect password.'));
         }

         var userinfo = user.get();

         return done(null, userinfo);

       }).catch(function(err) {

         console.log("Error:", err);

         return done(null, false, req.flash('genError', 'Something went wrong with your Signin'));

       });

     }
   ));
 }

【讨论】:

  • TypeError: (中间值).then 不是函数
  • 这个在我的环境中也不起作用。更多错误...但是谢谢。
  • TypeError: User.findOne(...).then 不是函数
【解决方案2】:

这对我有用

passport.use('login', new LocalStrategy({
        // by default, local strategy uses username
        usernameField : 'email',
        passwordField : 'password',
        passReqToCallback : true
    },
    function(req, email, password, done) {
        if (email) email = email.toLowerCase();

        // asynchronous
        process.nextTick(function() {
            User.findOne({ 'email' :  email }, function(err, user) {
                // if there are any errors, return the error
                if (err)
                    return done(err);

                // if no user is found, return the message
                if (!user)
                    return done(null, false, req.flash('loginMessage', 'No user found.'));

                if (!user.validPassword(password))
                    return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));

                // all is well, return user
                else
                    return done(null, user);
            });
        });

    }));

【讨论】:

    【解决方案3】:

    它可能来自您将代码包装到process.nextTick()

    如果您想进行异步调用来验证您的用户,您可以使用 Promise 来代替 @Damien Gold 回答。我无法测试它,但类似下面的东西可能会起作用。

    如果Users.findOne() 不可用,您可以使用延迟承诺或承诺(让我知道我可以使用示例代码调整我的答案)

    let promise = require('bluebird'); // or any other promise library
    
    passport.use('local-login', new LocalStrategy({
        usernameField : 'email',
        passwordField : 'password'
        //passReqToCallback : true // allows us to pass in the req from our route (lets us check if a user is logged in or not)
    },
    function( email, password, done) {
        if (email)
            email = email.toString().toLowerCase();
    
            // not sure which db driver you are using but most implement promises now
    
            Let defer = promise.defer();
    
            User.findOne({ email:  email }, function(err, user) {
                if (err) { return defer.reject(err); }
    
                 return defer.resolve(user);
            });
    
            defer.promise
            .then(function(user) {
                // if no user is found, return the message
                if (!user)
                    return done(null, false, {message: 'No user found.'});
    
                if (!user.validPassword(password))
                    return done(null, false, {message: 'Oops! Wrong Password'});
    
                // all is well, return user
                else
                    return done(null, user);
            }).catch(function(err) {
                // if there are any errors, return the error
                return done(err);
            });
        });
    }));
    

    【讨论】:

    • 我编辑了我的帖子。只是npm install 任何承诺库(蓝鸟,何时,...)出于好奇,用户背后是什么?你熟悉 Promise 吗?
    • 此代码没有错误,但 failureRedirect: '/login' 发生
    • 如果我没记错的话,它会在用户未被识别时发生。默认情况下,护照会将您重定向到 /login 路由。根据我对您的错误的猜测,您可能没有定义这样的路线
    • 我已经定义了路由。
    猜你喜欢
    • 1970-01-01
    • 2016-02-26
    • 2013-04-01
    • 2016-03-06
    • 2017-06-30
    • 2018-04-28
    • 2019-02-14
    • 2021-10-02
    相关资源
    最近更新 更多