首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Passport登录和持久化会话

Passport登录和持久化会话
EN

Stack Overflow用户
提问于 2016-04-08 04:19:42
回答 5查看 44K关注 0票数 49

背景

我有一个用postman完全测试过的CRUD功能的应用程序。我已经尝试坚持登录了相当长的一段时间,但没有运气。我已经阅读并尝试了以下内容

但我只能注册和登录用户,不能使用会话持久化登录。

我的应用程序

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

我对身份验证/登录的理解

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

Passport设置

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

代码语言:javascript
复制
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);
    });
  });
};

这在服务器文件中被调用,如下所示

代码语言:javascript
复制
//code before
var user    = require('./models/user.js');
var auth    = require('./modules/auth.js')(app, user);
// code after

用于登录的路由

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

代码语言:javascript
复制
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’并得到以下响应。

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

那么下一步呢?

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

在我的server?

  • Should上,用户现在是否处于会话中?我将req.session.passport.user发送回客户端?

  • 将来的所有请求都需要会话ID吗?

测试会话

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

代码语言:javascript
复制
router.get('/checkauth', passport.authenticate('local'), function(req, res){

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

});

部分passport.authenticate('local') (我认为)是为了在提供对路由的访问权限之前测试用户会话是否存在,但我在运行此命令时从未得到200响应,即使在登录之后也是如此。

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

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

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2016-04-10 17:20:40

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

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

是否应该将req.session.passport.user发送回客户端?

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

将来的所有请求都需要会话ID吗?

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

测试会话的

passport.authenticate('local')用于从POST正文验证用户凭据。您应该仅对登录路由使用此选项。

但是要检查用户是否在所有其他路由上进行了身份验证,您可以检查是否定义了req.user

代码语言:javascript
复制
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!'
    });
});
票数 78
EN

Stack Overflow用户

发布于 2016-04-15 00:53:48

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

代码语言:javascript
复制
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这样的东西。

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

票数 17
EN

Stack Overflow用户

发布于 2016-04-14 00:08:41

根据passport documentationreq.user将设置为经过身份验证的用户。但是,为了使其正常工作,您将需要express-session模块。除了已有的东西外,您不需要任何其他东西即可使passport正常工作。

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

例如,您可以有一个中间件函数,可以在任何想要进行身份验证的路由上使用它。

authenticated.js

代码语言:javascript
复制
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');
    }
};

控制器

代码语言:javascript
复制
var authenticated = require('./authenticated');

router.get('/protectedpage', authenticated, function(req, res, next) {
    //Do something here
});
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36486397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档