Node.js Passport登录和持久会话 背景

Node.js Passport登录和持久会话 背景,node.js,session,authentication,express,passport.js,Node.js,Session,Authentication,Express,Passport.js,我有一个平均应用程序与CRUD功能充分测试邮递员。我一直试图坚持登录相当长一段时间了,现在没有运气。我已经阅读并尝试了以下内容 再加上一大堆其他轻松的阅读材料(很多问题) 但我只能注册和登录一个用户,不能持久登录会话 我的应用程序 是指向完整github repo的链接(如果您正在查找最新的更改,请检查开发分支) 我对Auth/Login的理解 下面是我对用户登录的理解,包括我的项目中的代码示例、postman结果的屏幕截图以及控制台日志 护照设置 我有以下auth.js文件,它配置

我有一个平均应用程序与CRUD功能充分测试邮递员。我一直试图坚持登录相当长一段时间了,现在没有运气。我已经阅读并尝试了以下内容

  • 再加上一大堆其他轻松的阅读材料(很多问题)
但我只能注册和登录一个用户,不能持久登录会话

我的应用程序 是指向完整github repo的链接(如果您正在查找最新的更改,请检查开发分支)

我对Auth/Login的理解 下面是我对用户登录的理解,包括我的项目中的代码示例、postman结果的屏幕截图以及控制台日志

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

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);
});
router.get('/checkauth', passport.authenticate('local'), function(req, res){

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

});
经邮递员测试,这条路线有效。我输入详细信息“joe”和“pass”,并得到以下响应

当点击此路由时,我们还可以在控制台中看到用户被序列化

那么接下来呢? 这就是我迷路的地方。我有几个问题

  • 用户现在是否正在我的服务器上进行会话
  • 我是否应该将
    req.session.passport.user
    发送回客户端
  • 我是否需要所有未来请求的会话ID
  • 测试会话 我有一个测试会话的第二个路由设置,如下所示

    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);
    });
    
    router.get('/checkauth', passport.authenticate('local'), function(req, res){
    
        res.status(200).json({
            status: 'Login successful!'
        });
    
    });
    
    部分
    passport.authenticate('local')
    (我想)是为了在授予对路由的访问权限之前测试用户会话是否存在,但我在运行该部分时从未得到200响应,即使是在登录之后

    此路由是否期望头中传递一个
    req.session.passport.user
    ,或者作为需要auth的http请求上的数据参数


    如果我遗漏了什么或者我理解错了什么,请告诉我,任何意见都是非常感谢的。谢谢大家。

    我不知道如何检查所有现有会话,但Passport正在处理会话ID的颁发。登录后,请尝试检查测试端点上是否有req.user,该用户现在是否正在我的服务器上进行会话?

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

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

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

    我是否需要未来所有请求的会话ID?

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

    测试会话

    passport.authenticate('local')
    用于从邮件正文验证用户凭据。您应该仅在登录路径中使用此选项

    但要检查用户是否在所有其他路由中经过身份验证,您可以检查是否定义了
    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!'
        });
    });
    
    根据,
    req.user
    将被设置为经过身份验证的用户。但是,为了使其正常工作,您需要
    快速会话
    模块。你不应该需要任何东西,除了你已经有护照工作

    就测试会话而言,您可以使用一个中间件功能来检查是否设置了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
    });
    

    正如@hassansin所说,您需要使用一个实现会话管理的中间件。session()中间件用于将passport框架连接到会话管理,而不是单独实现会话。您可以使用来实现会话管理。您需要按照以下方式修改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);
        });
      });
    };
    
    请注意,在本例中,会话引擎正在使用内存存储,如果您扩展应用程序并应用负载平衡,它将无法工作。当您达到这种开发状态时,将需要类似的东西


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

    Passport.js无法正常工作,因为它将会话存储在服务器中(错误且不可扩展)。您不希望在服务器中存储任何会话数据(保持无状态),因为这样您就可以扩展集群并处理更多请求

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


    这是一个。

    不起作用的部分是“测试会话”部分。我已登录,但无法请求checkauth。但是如果我不发送会话id,路由如何知道im是正确的用户?有没有办法查看服务器上哪些会话处于活动状态?谢谢Hassansin,会话现在正在我的应用程序上运行。如果我在每个路由上使用req.isAuthenticated()而不是req.user来检查用户是否登录,会发生什么情况?那么,在节点应用程序重新启动后如何保持用户登录?因为现在它只是记忆中的一个片段session@hassansin和邮递员