如何正确使用Passport.js?

我在用 :

  • Node.js的
  • Express 4.0
  • Passport.js
  • Google OAuth 2进行身份validation

对于每个用户,我存储在一个MySQL数据库(我没有关于这项技术的select)从他的谷歌个人资料(电子邮件等),访问和刷新令牌的一些信息,以及用户提供的额外信息他注册在我的应用程序。

我已经看到passport.js的不同用途,特别是关于如何将这些信息存储在会话中。

  1. 在passport.js的configuration页面上 ,我不太了解以下代码块的要点:

    passport.deserializeUser(function(id, done) { User.findById(id, function(err, user) { done(err, user); }); }); 

    基本上,每次用户提出请求或访问页面时,都会向DB提出请求并检索信息。 有什么意义? 它使应用程序变慢。 当serializeUser被调用时(即信息存储在会话中),不应该检索数据库的信息吗?

  2. 我已经读过,在session中存储太多的信息可能会减慢应用程序。 什么是“太多”? 多less会减慢应用程序? 有人知道是否有testing吗? 我的应用程序页面需要一组关于我的用户的不同数据(例如,主页只需要他的名字,而configuration文件页面将需要一切,另一页需要知道他拥有的汽车等)。 如果passport.authenticate检查用户是否存在于数据库中(因此限制对数据库的读取请求大约为一个),或者只在会话中存储他的ID,并让我的页面向数据库在必要时?

  3. 我有另一个问题:在注册过程中,我首先让用户login他的Google帐户,我在某处存储他的个人资料的详细信息,让他填写一个额外信息的表格,然后我将所有内容插入到数据库中。 问题是我不知道如何正确存储他的Google帐户的详细信息,直到他们被插入数据库。 目前,我将它们存储在session ,然后在插入成功时删除它。 更具体地说,当我的数据库中找不到现有用户时,我在我的passport.authenticatecallback中:

     return done(null,false,userInfo); 

    因此,用户没有通过身份validation,我有两个问题:我必须存储该userInfo ,直到用户注册,我必须在注册完成后使用req.login() “手动”login他。

    我应该允许他login自己的Google帐户后进行身份validation吗? 如果他没有完成注册,会不会对我造成安全问题?

  4. 最后,我读了关于使用Reddis。 这会帮助我解决这些问题吗?

非常感谢你 !

1)serializeUser正在过滤数据并将其存储在会话cookie中。 一般情况下,如果可以的话,在cookie中储存量较less 你将打电话给数据库有关用户的数据,所以你可以只存储一个用来检索和重build用户的ID,如在deserializeUser中所见。

来自cookie的请求由客户端提供给服务器,服务器将cookie反序列化为数据,解密cookie内容或从数据库中检索用户数据。 然后,响应出来,服务器序列化客户端数据,刮掉你不会存储在cookie中的东西,并把它们放在数据库中,只是在cookie中留下一个id。

如果你正在进行encryption,那么当你想通过运行多个机器来扩展时,这很容易被搞砸,每台机器都需要能够解密数据(不是很难,但是不必要的复杂性)

将未encryption的数据放在cookie中并不是最好的,除此之外cookie中的任何内容都可以为用户添加额外的带宽使用情况。

2)数据库调用应该是非常快的,如果他们不是你在其他地方有一个痛苦的用户体验。 换句话说,我强烈的意见是,有一个压倒性的说法,远离cookies。

考虑到cookie随每个请求一起发送; 更聪明的做法是,将用户数据暂时(caching)在用户发出请求后加载,然后既不需要数据库调用,也不需要开销而用户正在您的网站上。

老实说,你应该罚款,而不是caching。 专注于让您的应用程序最小复杂性。 这样,您可以根据用户反馈更快地修改它,并减less错误。

3)当我和护照一起玩时,我也有类似的问题。 我会让护照做好工作,给用户授予护照级的validation(所以是的,他们已经login),然后分别做更多的数据收集。 如果您担心安全问题,请在完成login之前完成此护照级validation,并且在升级到完全login之前需要更多数据。

我可以做到这一点,但这是我的build议。

4)Redis适用于有多个节点实例并希望在内存中存储某些内容(例如计数器或caching的用户数据)的情况。 这样,节点代码中的variables就不会包含关于用户的caching数据,而当用户返回并且负载均衡器将其映射到其他实例时,另一个节点实例无法利用这些variables。 http://www.ourdailycodes.com/2013/09/redis-when-should-i-use-it.html

编辑:我应该添加该会话使用一个cookie,但只给用户一个唯一的令牌,服务器可以理解,以便服务器可以重新收集用户的会话数据时,与相应的会话令牌接收连接。 我的理解是,这是Session正常工作的正确途径…但是它因实现而有所不同(如果我在此错误,有人纠正我)。

我使用了node.js这是来自文档的代码:

 passport.serializeUser(function(user, done) { done(null, user.id); }); passport.deserializeUser(function(id, done) { User.findById(id, function (err, user) { done(err, user); }); }); 

这是代码,我修改了更好的理解:

 var passport = require ('passport') passport.serializeUser (function(user, done) { done(null, user.id); }); passport.deserializeUser(function(id, done) { var user = _.find(fixtures.users, 'id', id) if (user) { done (null, user); } else { done (null, false) } }); module.exports = passport; 

在serializeUser中,客户端使用'id'发送cookie。 serializeUser中的'(user)'参数是用户configuration文件,客户端仅使用用户configuration文件中的'id'向服务器发送请求。 完成callback传递user.id到服务器。

在反序列化用户中,服务器将查看数据库并从serializedUser中find具有该“id”的用户并返回用户configuration文件。 我用'lodash'来使用find和remove方法。

 var _ = require ('lodash') var user = _.find(fixtures.users, 'id', id) 

find将查找用户ID并返回该用户的个人资料。 关于lodash的更多细节在这里: lodash 。 之后,我检查用户是否存在,然后返回用户,否则返回false。

最后,我出口护照。

 module.exports = passport;