简体   繁体   English

如何正确使用Passport.js?

[英]How to properly use Passport.js?

I am using : 我在用 :

  • Node.js Node.js的
  • Express 4.0 快递4.0
  • Passport.js Passport.js
  • Google OAuth 2 for Authentication Google OAuth 2用于身份验证

For each user, I store in a MySQL DB (I don't have the choice regarding this technology) some info from his Google Profile (email etc...), access & refresh tokens, and also additionnal info that the user provides when he registers on my app. 对于每个用户,我存储在MySQL数据库中(我没有关于此技术的选择)来自他的Google个人资料(电子邮件等...)的一些信息,访问和刷新令牌,以及用户提供的附加信息。他在我的应用程序上注册。

I have seen different uses of passport.js, specifically regarding how that info is stored in session. 我已经看到了passport.js的不同用途,特别是关于如何在会话中存储该信息。

  1. On passport.js's configure page , I don't really understand the point of the following block of code : passport.js的配置页面上 ,我真的不明白以下代码块的要点:

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

    Basically, each time the user makes a request, or visits a page, there's a request to the DB and information is retrieved. 基本上,每次用户发出请求或访问页面时,都会向DB请求并检索信息。 What is the point ? 有什么意义? It slows the app a lot. 它减慢了应用程序的速度。 Shouldn't the info from the DB be retrieved when serializeUser is called (ie. when the info is stored in session) ? 在调用serializeUser时(即,当信息存储在会话中时),不应该检索来自DB的信息吗?

  2. I have read that storing too much info in session can slow the app. 我已经读过在session中存储太多信息session降低应用程序的速度。 What is "too much" ? 什么是“太多”? How much will it slow the app ? 应用程序会减慢多少钱? Does someone know if there are tests somewhere ? 有人知道某处是否有测试? My app's pages require a different set of data about my user (for example, the homepage will only need his name whereas the profile page will need everything, another page will need to know what cars he owns etc...). 我的应用程序页面需要一组关于我的用户的不同数据(例如,主页只需要他的名字,而个人资料页面将需要所有内容,另一个页面需要知道他拥有的汽车等...)。 Should I store all that info in session when passport.authenticate checks if the user exists in the DB (thus limiting read-requests to the DB to approximately one), or only store in session his id and have my pages make additionnal requests to the DB when necessary ? passport.authenticate检查用户是否存在于数据库中时,我是否应该将所有信息存储在session中(从而将对数据库的读取请求限制为大约一个),或者仅在会话中存储他的ID并让我的页面向该用户发出附加请求。 DB有必要吗?

  3. Another issue I have : in the registration process, I first have the user log in on his Google Account, I store his profile's details somewhere , have him fill a form for additionnal info, and then I insert everything in the DB. 我的另一个问题是:在注册过程中,我首先让用户登录他的Google帐户,我将他的个人资料的详细信息存储在某个地方 ,让他填写表格以获取其他信息,然后我将所有内容都插入到数据库中。 The problem is I don't know how to properly store his Google Account details until they are inserted into the DB. 问题是我不知道如何正确存储他的Google帐户详细信息,直到它们插入数据库。 For the moment, I store them in session , and then delete that when the insertion is successful. 目前,我将它们存储在session ,然后在插入成功时删除它。 More specifically, when no existing user is found in my DB, I do, in my passport.authenticate callback: 更具体地说,当我的数据库中没有找到现有用户时,我会在我的passport.authenticate回调中找到:

     return done(null,false,userInfo); 

    Thus, the user is not authenticated and I have 2 issues : I have to store that userInfo somewhere until the user is registered and I have to log him "manually" using req.login() after the registration is complete. 因此,用户未经过身份验证,我有两个问题:我必须将userInfo存储在某处,直到用户注册为止,我必须在注册完成后使用req.login() “手动”登录。

    Should I allow him to be authenticated as soon as he logs in on his Google Account ? 我是否应该在登录Google帐户后立即对其进行身份验证? Wouldn't that cause security issues for me if he does not complete his registration ? 如果他没有完成注册,这不会给我带来安全问题吗?

  4. Lastly, I have read about using Reddis. 最后,我读过有关使用Reddis的内容。 Would that help me with these issues ? 这会帮助我解决这些问题吗?

Thank you very much ! 非常感谢你 !

1) serializeUser is filtering the data and storing it in the session cookie. 1)serializeUser过滤数据并将其存储在会话cookie中。 generally store less in the cookie if you can. 如果可以,通常在cookie中存储较少。 You are going to call the db for data about the user anyways so you can just store an ID used to retrieve and reconstruct the user, as seen in deserializeUser. 无论如何,您将调用数据库以获取有关用户的数据,因此您只需存储用于检索和重新构建用户的ID,如deserializeUser中所示。

Request coming in the cookie is provided to the server by the client, the server deserializes the cookie into data, either decrypting cookie content or retrieving user data from the db. 来自cookie的请求由客户端提供给服务器,服务器将cookie反序列化为数据,解密cookie内容或从数据库检索用户数据。 Then response headed out the server serializes the client data, scraping off things you wouldn't store in the cookie and putting them in the db, just leaving an id in the cookie. 然后响应出来,服务器序列化客户端数据,刮掉你不会存储在cookie中的东西并将它们放入数据库中,只需在cookie中留下一个id。

if you are doing encryption then this can easily be screwed up when you want to scale by running multiple machines who each need to be able to decrypt the data (not really hard, but unnecessary complexity) 如果你正在进行加密,那么当你想通过运行多台机器进行扩展时,这很容易被搞砸,每台机器都需要能够解密数据(不是很难,但是不必要的复杂性)

Having unencrypted data just lying in the cookie isn't the best, and besides anything in the cookie can add that inkling of extra bandwidth usage for the user. 将未加密的数据放在cookie中并不是最好的,除了cookie中的任何内容之外,还可以为用户添加额外带宽使用量。

2) The database calls should be very fast, if they aren't you are going to have a suffering user experience elsewhere anyways. 2)数据库调用应该非常快,如果不是,那么无论如何你都会在其他地方遇到痛苦的用户体验。 In other words, my strong opinion is that there is an overwhelming argument for staying away from cookies. 换句话说,我强烈的观点是,对于远离cookie存在压倒性的争论。

consider that cookies are sent with each request; 考虑每次请求都会发送cookie; it would be smarter to, instead of shoving data into the session and having it add overhead, have the user data load up temporarily (cached) for a bit after the user makes a request, and then have neither database calls nor overhead from the cookie while the user is actively on your site. 它会更聪明,而不是将数据推入会话并增加开销,在用户发出请求后暂时(缓存)用户数据加载,然后既没有数据库调用也没有来自cookie的开销而用户主动在您的网站上。

honestly you should be fine at first without caching. 老实说,一开始你应该没有缓存。 Focus on getting your app up with minumum complexity. 专注于以最低的复杂性来提升您的应用程序。 This way you can modify it according to user feedback faster and have fewer mistakes. 这样您就可以根据用户反馈更快地修改它并减少错误。

3) When I played with passport I had a similar issue. 3)当我玩护照时,我遇到了类似的问题。 I would let passport do its job and grant passport-level-verification to the user (so yes they are logged in), then do more data collection separately. 我会让护照完成它的工作,并向用户授予护照级别的验证(所以是的,他们已经登录),然后单独进行更多的数据收集。 If you are concerned about security then make this passport-level verification not fully logged in, and require more data before upgrading to fully logged in. 如果您担心安全问题,请将此护照级别的验证未完全登录,并在升级到完全登录之前需要更多数据。

I could be very off the mark with this one, but that's my recommendation. 我可能与这个非常不合适,但这是我的建议。

4) Redis is good for times when you have multiple node instances and want to store something in memory (say a counter, or that cached user data). 4)当你有多个节点实例并希望将某些东西存储在内存中时(例如计数器或缓存的用户数据),Redis很适合。 This way you don't have variables in the node code holding onto cached data about a user, which another node instance can't take advantage of when the user comes back and the load balancer shoots them to a different instance. 这样,您不会在节点代码中保留有关用户的缓存数据的变量,当用户返回并且负载均衡器将其射向另一个实例时,另一个节点实例无法利用该变量。 http://www.ourdailycodes.com/2013/09/redis-when-should-i-use-it.html http://www.ourdailycodes.com/2013/09/redis-when-should-i-use-it.html

EDIT: I should add that session uses a cookie, but only gives the user a unique token the server understands, so that the server can re-gather the user's session data when a connection is received with an accompanying session token. 编辑:我应该添加该会话使用cookie,但只给用户一个服务器理解的唯一令牌,以便服务器可以在收到连接并附带会话令牌时重新收集用户的会话数据。 My understanding is that this is the generally correct way for Session to work... but that it varies by implementation (Someone correct me if I am wrong here). 我的理解是,这是Session工作的一般正确方式......但它因实现而异(如果我在这里错了,有人会纠正我)。

I used node.js This is code from documentation : 我用了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);
   });
});

and this is the code, I modified to understand better : 这是代码,我修改为更好地理解:

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;

In serializeUser, client sending cookie with an 'id'. 在serializeUser中,客户端发送带有“id”的cookie。 Here '(user)' argument in serializeUser is user profile and client using only 'id' from user profile to send request to server. serializeUser中的'(user)'参数是用户配置文件,客户端仅使用用户配置文件中的'id'向服务器发送请求。 done callback passing user.id to server. 完成回调将user.id传递给服务器。

In deserializedUser, server will look into database and find the user with that 'id' from serializedUser and return the user profile. 在deserializedUser中,服务器将查看数据库并从serializedUser中找到具有该“id”的用户并返回用户配置文件。 I used 'lodash' to use find and remove methods. 我使用'lodash'来使用find和remove方法。

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

find will look for user id and return user profile with that id . find将查找用户ID并返回具有该id的用户配置文件。 More details about lodash is here : lodash . 关于lodash的更多细节在这里: lodash After that I am checking if user exist then return user otherwise return false. 之后我检查用户是否存在然后返回用户否则返回false。

At the end, I am exporting passport. 最后,我出口护照。

module.exports = passport;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM