passport.js 成功认证后未调用 next()。

5

我正在使用passport.js进行身份验证。似乎在成功验证后,passport不会调用next(),因此我的Express路由永远不会执行。我发现这种行为适用于我实施的所有身份验证策略。

app.js

app.use(passport.initialize());
passport.use(authentication.local);
passport.use(authentication.bearer);

routes.setup(app, passport);

routes.js

function setup (app, passport) {
  // routes.authentication.token not called, despite successful authentication.
  app.post('/authentication/token', passport.authenticate('local'), 
      routes.authentication.token);
}

authentication.js

var local = new LocalStrategy(
  {
    usernameField: 'email',
    passwordField: 'password'
  },

  function (email, password, done) {
    var user = new User({ email: email });

    user.fetch({
      success: function (user) {
        if (bcrypt.compareSync(password, user.get('encryptedPassword'))) {
          // This line shows in the console, but the route after is never executed.
          console.log("LocalStrategy success!");
          done(null, user); // Tell passport we have success.
        } else {
          done(null, false, { message: 'The password given was incorrect.' });
        }
      },

      error: function (err) {
        done(null, false, { message: 'The email address (' + email + ') does not belong to any user.' });
      }
    });
  }
);

更新

这里提供一个单文件复现问题的示例,可能比上面不完整的多文件问题更容易理解:

// ----------------------------------------------------------------------------
// Environment/Configuration
// ----------------------------------------------------------------------------
var config =  require('./lib/config');

var environment = process.env.NODE_ENV || 'development';
config.load(__dirname + '/config/environment', environment);
config.loadDev(__dirname + '/config/environment', environment);

// ----------------------------------------------------------------------------
// Requirements
// ----------------------------------------------------------------------------
var express = require('express')
  , passport = require('passport')
  , bcrypt = require('bcrypt')
  , LocalStrategy = require('passport-local').Strategy
  , User = require('./app/models/user');


// ----------------------------------------------------------------------------
// HTTP Server
// ----------------------------------------------------------------------------
var app = express();

// ----------------------------------------------------------------------------
// Middleware
// ----------------------------------------------------------------------------
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);

app.use(passport.initialize());

passport.use(new LocalStrategy(
  {
    usernameField: 'email',
    passwordField: 'password'
  },

  function (email, password, done) {
    console.log("Authenticating user.", email, password);
    var user = new User({ email: email });

    user.fetch({
      success: function (user) {
        if (bcrypt.compareSync(password, user.get('encryptedPassword'))) {
          // This log statement shows in the console.
          console.log("LocalStrategy success!");
          done(null, user);
        } else {
          done(null, false, { message: 'The password given was incorrect.' });
        }
      },

      error: function (err) {
        console.log('LocalStrategy failure!');
        done(null, false, { message: 'The email address (' + email + ') does not belong to any user.' });
      },

      complete: function (user, res) {
        console.log(res);
      }
    });
  }
));

app.post('/authentication/token', passport.authenticate('local'), function (req, res, next) {
  // This line is never reached.
  console.log('I\'m authenticated!');
});

// ----------------------------------------------------------------------------
// Boot
// ----------------------------------------------------------------------------
app.listen(process.env.PORT);
console.log('Server started on port: %d', process.env.PORT);

routes.authentication.token 定义在哪里?routes.js 中没有这个路由。 - user568109
@user568109 这个已经在文件的其他地方定义了。如果我用一个调用console.log()的函数替换routes.authentication.token,那么这个函数永远不会被执行。 - Ian Christian Myers
2个回答

1
问题似乎出现在Express中间件的排序上。需要在app.use(app.router);之前设置app.use(passport.initialize());和passport。请保留HTML标签。

0

我曾经遇到过同样的问题,后来发现是我不小心从我的serializeUser函数中删除了回调函数。

也许你可以检查一下你的序列化和反序列化函数是否正确。

下面的代码是我使用的,你的可能会有所不同,具体取决于你是使用用户的ID进行序列化还是其他字段。

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

passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user) {
        done(err, user);
    });
});

我没有使用会话,因为这是针对API的,所以我也没有使用serializeUser或deserializeUser。 我已经尝试开启会话并添加用户序列化,但没有帮助。 - Ian Christian Myers
如果您没有使用session,应该在身份验证调用中禁用它们:passport.authenticate('local', { session: false }); - Jared Hanson

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