护照login和持续会话

背景

我有一个与邮差完全testing的CRUDfunction的平均应用程序。 我一直试图坚持login相当一段时间,没有运气。 我已阅读并尝试以下

  • 护照文件
  • toon io的博客关于login
  • 快速会议
  • Scotch io,节点auth变得容易
  • 再加上一些其他的阅读材料(许多SO问题)

但我只能注册和login一个用户,而不是坚持login会话。

我的应用程序

这里是一个链接到完整的github回购(如果你正在寻找最新的变化检查开发分支)

我对authentication/login的理解

这里是我的理解用户login与我的项目代码示例和邮递员结果以及控制台日志的截图。

护照设置

我有以下auth.js文件,它configuration护照

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 

路由login

在我的路线我有login路线如下

 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); }); 

这条路线与邮差testing一样。 我input细节“乔”和“通过”,并得到以下回应。

在这里输入图像描述

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

在这里输入图像描述

那么接下来呢?

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

  1. 用户现在在我的服务器上的会话吗?
  2. 我应该把req.session.passport.user回客户端吗?
  3. 我是否需要所有未来请求的会话ID?

testing会话

我有第二个路由设置来testing会话,如下所示

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

部分passport.authenticate('local') (我认为)在那里testing用户会话是否存在访问路由之前,但我从来没有得到200响应当我运行这个,即使login后。

这条路线是否req.session.passport.user在头部传递req.session.passport.user ,或者在需要auth的http请求上使用数据参数?

如果我错过了任何东西或者有什么不对的地方,请告诉我,任何意见都会被赞赏。 谢谢大家。

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

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

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

如果您的客户端在login时期望user资源,那么您应该。 否则,我没有看到任何理由发送用户对象到客户端。

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

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

testing会话

passport.authenticate('local')用于从POST主体validation用户凭证。 你只能用这个login路由。

但要检查用户是否在所有其他路由中被authentication,您可以检查是否定义了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!' }); }); 

正如@hassansin所说,你需要使用一个实现会话pipe理的中间件。 passport.session()中间件是将护照框架连接到会话pipe理,而不是单独实现会话。 您可以使用express-session中间件来实现会话pipe理。 你需要以下面的方式修改你的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会话存储那样的东西。

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

根据护照文件 , req.user将被设置为已通过身份validation的用户。 为了这个工作,你将需要express-session模块。 除了你已经拥有的工作护照以外,你不需要任何其他的东西。

就testing会话而言,您可以有一个中间件function来检查req.user是否已设置,如果是,我们知道用户已通过身份validation,如果不是,则可以redirect用户。

例如,你可以有一个中间件function,你可以使用任何你想要authentication的路由。

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 }); 

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