Passport.js serializeUser 和 desializeUser 从未被调用过?

Passport.js serializeUser and desializeUser are not being called ever?

Passport-local 有问题。 serializeuserdeserializeUser 似乎都没有被调用。在阅读了关于 SO 的其他帖子后,似乎很多遇到此问题的人都不包括 bodyParser

这是我的 app.js:

var express = require('express');
var app = express();

var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var db_config = require('./config/database');
var mongoose = require ('mongoose');

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

//loads passport implementation
require('./config/passport')(app);

//loads all routes
require('./config/routes')(app);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  //initialize connection to database
  mongoose.connect(db_config.development);

  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// development error handler
// will print stacktrace
if (app.get('env') === 'test') {
  //initialize connection to database
  mongoose.connect(db_config.test);

  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

if(app.get('env') === 'production'){
  //initialize connection to database
  mongoose.connect(db_config.production);

  // production error handler
  // no stacktraces leaked to user
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: {}
    });
  });
}

module.exports = app;

这里是config/passport.js:

module.exports = function(app){
  var passport = require ('passport');
  var LocalStrategy = require('passport-local').Strategy;
  var session = require('express-session');
  var User = require('../models/user.js');
  // =========================================================================
  // passport session setup ==================================================
  // =========================================================================
  // required for persistent login sessions
  // passport needs ability to serialize and unserialize users out of session

  // used to serialize the user for the session
  passport.serializeUser(function(user, done) {
    console.log('serialize');
    done(null, user._id);
  });

  // used to deserialize the user
  passport.deserializeUser(function(id, done) {
    console.log('deserialize');
    User.findById(id, function(err, user) {
      done(err, user);
    });
  });

  //configure passport http-basic strategy
  passport.use(new LocalStrategy({
    usernameField: "username",
    passwordField: "password"
  },
  function(username, password, done){
    User.findOne({username: username}, function(err, user){
      if(err) return done(err);
      if(!user || !user.validatePassword(password)) return done(null, false);
      console.log("inside LocalStrategy: " + user);
      return done(null, user);
    });
  }));

//setup express-session
app.use(session({
  secret: "secret",
  saveUninitialized: true,
  resave: true
}));

app.use(passport.initialize());
app.use(passport.session());

return passport;
};

这是我的 routes.js:

module.exports = function(app){
  var routes = require('../routes/index');
  var users = require('../routes/users');
  var walks = require('../routes/walks');

  var isAuthenticated = function(req, res, next){
    if(req.isAuthenticated())
      next();
    res.status(401).send('You must login first.');
  };

  app.use('/', routes);
  app.all('*', isAuthenticated);
  app.use('/users', users);
  app.use('/walks', walks);
};

这里是 routes/index.js:

var router = require('express').Router();
var passport = require('passport');
var controller = require('../controllers/index');

router.get('/', controller.index);

router.post('/signup', controller.signup);

router.post('/login', passport.authorize('local'), controller.login);

module.exports = router;

最后是 controller/index.js:

var User = require('../models/user.js');
var handleError = require('../handlers/error');
var controller = {};

controller.index = function(req, res, next) {
  res.render('index', { title: 'Express' });
};

controller.signup = function(req, res){
  console.log(req.body);
  var user = new User();
  user.username = req.body.username;
  user.password = req.body.password;

  user.save(function(err, user){
    if(err) {
      console.log(err.code);
      handleError(res, err);
    }
    return res.send(user);
  });
};

controller.login = function(req, res){
  console.log('inside /login');
  console.log('req.user: ' + req.user);
  console.log('req.session: ');
  console.log(req.session);
  console.log('req.body: ');
  console.log(req.body);
  res.send(req.user);
};

module.exports = controller;

POSTMAN 中,我首先创建一个 user,其中包含对 /signup 的 POST 请求,其中:

{
 "username": "bob",
 "password": "password123"
}

然后我用相同的凭据 POST 到 /login,这是输出:

inside LocalStrategy: { __v: 0,
  username: 'bob',
  password: 'a$Oa/Q9C5Elsoa0P4427P6fOXWIKerlD937FYgLFrwCWwXxGW1gbsoW',
  _id: 5685d6845c7b208693b71091 }
inside /login
req.user: undefined
req.session:
Session {
  cookie:
   { path: '/',
     _expires: null,
     originalMaxAge: null,
     httpOnly: true } }
req.body:
{ username: 'bob', password: 'password123' }
POST /login 200 205.704 ms - -

如您所见,serializeUserdeserializeUser 中的 console.log() 都没有被调用。为什么是这样?我在这里完全不知所措,老实说,我不知道还能尝试什么。

这个:

router.post('/login', passport.authorize('local'), controller.login);

应该是这样的:

router.post('/login', passport.authenticate('local'), controller.login);

passport.authorize() 用于将 third-party 授权响应连接到 already-authenticated 用户。