Passport登录和持久会话

时间:2016-04-07 20:19:42

标签: node.js session authentication express passport.js

背景

我有一个MEAN应用程序,CRUD功能已经完全通过postman进行测试。我一直试图坚持登录很长一段时间没有运气。我已阅读并尝试以下

但我只能注册并登录用户,而不是通过会话持久登录。

我的应用

Here是完整github仓库的链接(如果您正在寻找最新的更改,请检查开发分支)

我对Auth / Login

的理解

以下是我对用户登录的理解,其中包含我的项目中的代码示例以及邮递员结果的屏幕截图以及控制台日志。

护照设置

我有以下auth.js文件,它配置了护照

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;

module.exports = function(app, user){

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

  // passport config
  passport.use(new LocalStrategy(user.authenticate()));

  passport.serializeUser(function(user, done) {
    console.log('serializing user: ');
    console.log(user);
    done(null, user._id);
  });

  passport.deserializeUser(function(id, done) {
    user.findById(id, function(err, user) {
      console.log('no im not serial');
      done(err, user);
    });
  });
};

这在服务器文件中调用,如

//code before
var user    = require('./models/user.js');
var auth    = require('./modules/auth.js')(app, user);
// code after

登录路由

在我的路线中,我的登录路线如下

router.post('/login', function(req, res, next) {

  passport.authenticate('local', function(err, user, info) {

    if (err) {
        return next(err);
    }

    if (!user) {
        return res.status(401).json({
            err: info
        });
    }

    req.logIn(user, function(err) {

        if (err) {
            return res.status(500).json({
                err: 'Could not log in user'
            });
        }

        res.status(200).json({
            status: 'Login successful!'
        });

    });
  })(req, res, next);
});

此路线有效经过邮递员测试。我输入详细信息'joe'和'pass'并得到以下回复。

enter image description here

当这条路线被击中时,我们也可以在控制台中看到用户被序列化。

enter image description here

接下来是什么?

这是我迷路的地方。我有几个问题。

  1. 用户现在是否在我的服务器上的会话中?
  2. 我应该将req.session.passport.user发回给客户吗?
  3. 我将来是否需要会话ID?
  4. 测试会话

    我有第二个路由设置用于测试会话,如下所示

    router.get('/checkauth', passport.authenticate('local'), function(req, res){
    
        res.status(200).json({
            status: 'Login successful!'
        });
    
    });
    

    部分passport.authenticate('local')(我认为)可以测试用户会话是否存在,然后才能访问该路由,但即使在登录后我也没有得到200响应。

    此路由是否期望在头部传递req.session.passport.user或在需要身份验证的http请求中作为数据参数?

    如果我错过了什么或者我理解了什么不对,请告诉我,任何意见都表示赞赏。谢谢大家。

5 个答案:

答案 0 :(得分:55)

用户现在是否在我的服务器上的会话中?

不,您需要在express-session之前使用app.use(passport.session());中间件将会话实际存储在内存/数据库中。该中间件负责为浏览器设置cookie,并将浏览器发送的cookie转换为req.session对象。 PassportJS仅使用该对象进一步反序列化用户。

我应该将req.session.passport.user发送回客户端吗?

如果您的客户端在登录时需要user资源,那么您应该这样做。否则,我认为没有理由将用户对象发送到客户端。

我是否需要在以后的所有请求中使用会话ID?

是的,对于将来的所有请求,都需要会话ID。但如果您的客户端是浏览器,则无需发送任何内容。浏览器会将会话ID存储为cookie,并将其发送给所有后续请求,直到cookie过期。 express-session将读取该Cookie并将相应的会话对象附加为req.session

测试会话

passport.authenticate('local')用于验证POST正文的用户凭据。您应该仅将此用于登录路由。

但要检查用户是否在所有其他路由中都经过身份验证,您可以检查是否已定义req.user

function isAuthenticated = function(req,res,next){
   if(req.user)
      return next();
   else
      return res.status(401).json({
        error: 'User not authenticated'
      })

}
router.get('/checkauth', isAuthenticated, function(req, res){

    res.status(200).json({
        status: 'Login successful!'
    });
});

答案 1 :(得分:11)

正如@hassansin所说,您需要使用实现会话管理的中间件。 passport.session()中间件是将护照框架连接到会话管理,而不是单独实现会话。您可以使用express-session middleware来实施会话管理。您需要按以下方式修改auth.js

var passport = require('passport');
var session = require('express-session');
var LocalStrategy = require('passport-local').Strategy;

module.exports = function(app, user){
  app.use(session({secret: 'some secret value, changeme'}));    

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

  // passport config
  passport.use(new LocalStrategy(user.authenticate()));

  passport.serializeUser(function(user, done) {
    console.log('serializing user: ');
    console.log(user);
    done(null, user._id);
  });

  passport.deserializeUser(function(id, done) {
    user.findById(id, function(err, user) {
      console.log('no im not serial');
      done(err, user);
    });
  });
};

请注意,在这种情况下,会话引擎正在使用内存存储,如果您扩展应用程序并应用负载平衡,它就不起作用。当您达到此开发状态时,将需要类似connect-redis session store的内容。

另请注意,您需要更改会话midleware调用中使用的密码值,并在所有应用程序实例上使用相同的值。

答案 2 :(得分:2)

根据passport documentationreq.user将设置为经过身份验证的用户。为了使其工作,您将需要express-session模块。除了你已经拥有的护照之外,你不应该做任何其他工作。

就测试会话而言,您可以使用中间件功能检查是否设置了req.user,如果是,我们知道用户已通过身份验证,如果不是,则可以重定向用户

例如,您可以使用中间件功能,可以在要进行身份验证的任何路由上使用。

<强> authenticated.js

module.exports = function (req, res, next) {
    // if user is authenticated in the session, carry on
    if (req.user) {
        next();
    }
    // if they aren't redirect them to the login page
    else {
        res.redirect('/login');
    }
};

<强>控制器

var authenticated = require('./authenticated');

router.get('/protectedpage', authenticated, function(req, res, next) {
    //Do something here
});

答案 3 :(得分:0)

我不知道检查所有现有会话的方法,但Passport正在处理会话ID的发布。登录后尝试检查您的测试端点上是否有req.user

答案 4 :(得分:0)

Passport.js不能很好地运行,因为它将会话存储在服务器中(不良且不可扩展)。您不想在服务器中存储任何会话数据(使其保持无状态),因为这样可能会扩展群集并处理更多请求。

如果您查看Passport.js库中的代码,则没有太多..自己构建它实际上可以更快,更高效。

这里是tutorial I wrote on connecting to Google in a much better way

相关问题