护照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细节“乔”和“通过”,并得到以下回应。
当这条路线被击中时,我们也可以在控制台中看到用户被序列化。
那么接下来呢?
这是我迷路的地方。 我有几个问题。
- 用户现在在我的服务器上的会话吗?
- 我应该把
req.session.passport.user
回客户端吗? - 我是否需要所有未来请求的会话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