如何正确使用Passport.js?
我在用 :
- Node.js的
- Express 4.0
- Passport.js
- Google OAuth 2进行身份validation
对于每个用户,我存储在一个MySQL数据库(我没有关于这项技术的select)从他的谷歌个人资料(电子邮件等),访问和刷新令牌的一些信息,以及用户提供的额外信息他注册在我的应用程序。
我已经看到passport.js的不同用途,特别是关于如何将这些信息存储在会话中。
-
在passport.js的configuration页面上 ,我不太了解以下代码块的要点:
passport.deserializeUser(function(id, done) { User.findById(id, function(err, user) { done(err, user); }); });
基本上,每次用户提出请求或访问页面时,都会向DB提出请求并检索信息。 有什么意义? 它使应用程序变慢。 当
serializeUser
被调用时(即信息存储在会话中),不应该检索数据库的信息吗? -
我已经读过,在
session
中存储太多的信息可能会减慢应用程序。 什么是“太多”? 多less会减慢应用程序? 有人知道是否有testing吗? 我的应用程序页面需要一组关于我的用户的不同数据(例如,主页只需要他的名字,而configuration文件页面将需要一切,另一页需要知道他拥有的汽车等)。 如果passport.authenticate
检查用户是否存在于数据库中(因此限制对数据库的读取请求大约为一个),或者只在会话中存储他的ID,并让我的页面向数据库在必要时? -
我有另一个问题:在注册过程中,我首先让用户login他的Google帐户,我在某处存储他的个人资料的详细信息,让他填写一个额外信息的表格,然后我将所有内容插入到数据库中。 问题是我不知道如何正确存储他的Google帐户的详细信息,直到他们被插入数据库。 目前,我将它们存储在
session
,然后在插入成功时删除它。 更具体地说,当我的数据库中找不到现有用户时,我在我的passport.authenticate
callback中:return done(null,false,userInfo);
因此,用户没有通过身份validation,我有两个问题:我必须存储该
userInfo
,直到用户注册,我必须在注册完成后使用req.login()
“手动”login他。我应该允许他login自己的Google帐户后进行身份validation吗? 如果他没有完成注册,会不会对我造成安全问题?
- 最后,我读了关于使用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;
- 如何仅在经过身份validation时才给予会话? 任何其他中间件订单将无法正常工作
- Rails,Node.js跨服务器authentication
- 为什么具有ObjectID(MongoDB)types的会话参数转换为string?
- 会话密钥在Express web框架中的重要性
- Express-session和express-socket.io-session在angular2 / typecript环境中不起作用
- 使用passport-local进行身份validation后,无法使用来自客户端的会话
- 如何使用Express和MongoStore从MongoDB集合中find一个会话
- PHP,nodeJS和会话
- Node Express – req.cookies和req.session.cookie之间的区别