Node.js Passport身份验证回调未被调用

23

我正在使用Nodejs Passport,通过以下代码测试发生错误时会发生什么:

passport.use(new LocalStrategy(
  function(username, password, done) {
    // asynchronous verification, for effect...
    process.nextTick(function () {
      findByUsername(username, function(err, user) {
    console.log('in auth function');
      return done('errortest');
        if (err) { return done(err); }
        if (!user) {
          return done(null, false, { message: 'Unknown user ' + username });
        }
        if (user.password != password) {
          return done(null, false, { message: 'Invalid password' });
        }
        return done(null, user);
      })
    });
  }
));

app.get('/logintest', function(req, res, next) {
console.log('before authenticate');
  passport.authenticate('local', function(err, user, info) {
console.log('authenticate callback');
    if (err) { return res.send({'status':'err','message':err.message}); }
    if (!user) { return res.send({'status':'fail','message':info.message}); }
    req.logIn(user, function(err) {
      if (err) { return res.send({'status':'err','message':err.message}); }
      return res.send({'status':'ok'});
    });
  })(req, res, next);
});

使用路由 /logintest?username=bob&password=s,我期望在控制台中看到 "before authenticate" 然后是 "in auth function" 再然后是 "authenticate callback",但实际上只显示前两个,接着是 "errortest",并且 "errortest" 也在浏览器中显示出来。

我还尝试了 return done({'message':'test'});,但控制台和浏览器中都显示 "[object Object]"。

这是有问题的吗?还是我漏掉了什么?

编辑:根据Jared Hanson的回复,在app.get()的第三个参数中添加此错误处理程序函数,可以让我捕获错误并返回适当的JSON:

...
    })(req, res, next);
  },
  function(err, req, res, next) {
    // failure in login test route
    return res.send({'status':'err','message':err.message});
  });
3个回答

19

你已经很好地理解了它,并且它正在按照预期工作。

如果出现任何错误,Passport会立即使用该错误的next()。如果您想自定义处理该错误,则可以使用错误处理中间件(详情请参阅:http://expressjs.com/guide/error-handling.html)。

自定义回调主要用于处理身份验证成功或失败(user == false)。像数据库连接等错误不会传递回回调函数,而是使用上述错误处理中间件进行处理。我考虑过更改这一点,但没有找到令人信服的理由。但是,如果您有任何未涵盖在上述内容中的用例,请告诉我。


1
感谢您的快速回复。我对node.js还比较新,但是这个应用场景是通过jquery ajax调用进行登录记录。我希望返回一个json对象,其中状态为“ok”表示成功,“fail”表示用户名/密码错误,“err”表示发生错误。(请注意我针对成功所做的代码编辑。) - KevinVictor
当调用自定义回调函数时,err 参数是否总是为 null? - KevinVictor
在 GitHub 的问题上发布了跟进,以便我可以更好地格式化代码。https://github.com/jaredhanson/passport-local/issues/15 - Jared Hanson

8

bodyparser.json() 是导致我的问题的原因,我通过为每个路由设置它来解决了这个问题(特别是在passport路由上)像这样:

app.post('/login', bodyParser.urlencoded({ extended: true }), function (req, res, next) {
          passport.authenticate('local', function (err, user, info) {
               if (err) { return next(err) }
               if (!user) {
                    console.log('bad');
                    req.session.messages = [info.message];
                    return res.redirect('/login')
               }
               req.logIn(user, function (err) {
                    console.log('good');
                    if (err) { return next(err); }
                    return res.redirect('/');
               });
          })(req, res, next);
     });

3

我也遇到过相同的问题。后来尝试添加了以下代码:

const bodyParser=require('body-parser');
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接