Passport登录和持久会话

Joe*_*oyd 34 authentication session node.js express passport.js

背景

我有一个MEAN应用程序,CRUD功能与邮递员完全测试.我一直试图坚持登录很长一段时间没有运气.我已经阅读并尝试了以下内容

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

我的应用程序

是一个完整的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);
    });
  });
};
Run Code Online (Sandbox Code Playgroud)

这在服务器文件中被调用

//code before
var user    = require('./models/user.js');
var auth    = require('./modules/auth.js')(app, user);
// code after
Run Code Online (Sandbox Code Playgroud)

登录路由

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

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);
});
Run Code Online (Sandbox Code Playgroud)

这条路线的工作原理与邮差测试.我输入详细信息'joe'和'pass'并得到以下回复.

在此输入图像描述

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

在此输入图像描述

接下来呢?

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

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

测试会话

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

router.get('/checkauth', passport.authenticate('local'), function(req, res){

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

});
Run Code Online (Sandbox Code Playgroud)

部分passport.authenticate('local')(我认为)在那里测试用户会话是否存在,然后才能访问路由,但是当我运行它时,即使在登录之后我也从未得到200响应.

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

如果我错过任何事情或者我理解错误请告诉我,任何意见都表示赞赏.谢谢大家.

has*_*sin 62

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

不,您需要先使用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!'
    });
});
Run Code Online (Sandbox Code Playgroud)


yei*_*iel 12

正如@hassansin所说,您需要使用实现会话管理的中间件.passport.session()中间件是将护照框架连接到会话管理,而不是单独实现会话.您可以使用express-session中间件来实现会话管理.您需要以下列方式修改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);
    });
  });
};
Run Code Online (Sandbox Code Playgroud)

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

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