ExpressJs Passportjs 为每个路由请求反序列化用户对象

ExpressJs Passportjs de-serializes user object for every request to a route

我有一个 ExpressJS 应用程序正在使用 Passportjs 向 Facebook 进行身份验证,并且一切正常,但有一个例外。

我在 /routes/ 下有 vehicle.js,其中包含一些需要身份验证的路由(router.gets 和 router.posts),有些则不需要。如果用户已登录,则 vehicle.js 处理的每个请求都会导致用户反序列化,这是 Mongoose 查找。 当向不需要身份验证的 router.get and/or router.post 发出请求时,如何避免这些不必要的 Mongoose 查找?

我已经查过这个 SO question 但它没有解决我的问题(我已经在 passport 之上声明了静态资源,所以它们没有经过身份验证)。

Passport app.js 中的配置如下所示:

// Configuring Passport
var passport = require('passport');
var expressSession = require('express-session');

app.use(expressSession({secret: 'thisIsSecret'}));
app.use(passport.initialize());
app.use(passport.session());

// Using the flash middleware provided by connect-flash to store messages in session
// and displaying in templates
var flash = require('connect-flash');
app.use(flash());

// Initialize Passport
var initPassport = require('./passport/init');
initPassport(passport);

//passing passport object could be the reason why all requested that are 
//mapped in vehicle cause user de-serialization. Not sure if there is any
//alternative approach than following line that passes passport??
var vehicle = require('./routes/vehicle')(passport);

以下isAuthenticated在vehicle.js

var isAuthenticated = function (req, res, next) {
  if (req.isAuthenticated())
    return next();
    // if the user is not authenticated then redirect him to the login page
    res.redirect('/vehicle/api/login');
}

之后是处理 logging inlogging out 的一系列 routes,以及对 vehicle 的一些操作。

module.exports = function(passport) {
  router.get('/api/login', function(req, res) {
    res.render('vehicle/login', { message: req.flash('message') });
  });
  router.post('/api/login', passport.authenticate('login', {
    successRedirect: '/vehicle/api/list/mine',
    failureRedirect: '/vehicle/api/list',
    failureFlash : true
  }));
  ...
  ...
  ...
  router.post('/api/upload', isAuthenticated, function(req, res) {
    //this route needs to  be authenticated, so it works fine, 
    //deserialization done, mongoose lookup, no problem
  }); 
  router.get('/api/image/:vehicleId/:filename', function(req,res) {
    //this route does not need authentication, but causes User 
    //de-serialization and Mongoose lookup
  }); 
 return router;
}

是不是因为下面这行,每次请求vehicle.js都会在用户登录时导致用户反序列化?

var vehicle = require('./routes/vehicle')(passport);

避免这种不必要的反序列化的一种方法是将不需要身份验证的路由从 vehicle.js 分离到另一个文件,并且不要将该护照对象传递到该文件(因为它被传递到vehicle.jsapp.js 中)。我不知道这是否是解决此问题的正确方法。

如果你使用 passport.session() 中间件,每条路由都会发生反序列化: https://github.com/jaredhanson/passport/blob/33075756a626999c6e2efc872b055e45ae434053/lib/strategies/session.js#L53-L69

解决方案是只将它添加到使用护照的人。

您可以将 passport 中间件包装在一个自定义中间件中,该中间件只会为您指定的路由调用它。所以代替:

app.use(passport.session());

你可以:

app.use(function(req, res, next){
  if(req.url.match('api/image'))
    next(); // do not invoke passport
  else
    passport.session()(req, res, next)
    // same as doing == app.use(passport.session())
});