Simple Auth With Passport-Local and deSerializeUse

2020-07-22 10:52发布

问题:

After reading an excellent description here on how deserialize and serialize user works in the Passport flow

Understanding passport serialize deserialize

I'm concerned about the performance impact of having deSerializeUser called on every request. All the examples I've seen (see below for one) have deserializeUser calling what looks like a database User.findById to do that work. Assuming you are not using a cdn for all your assets, that means many many database calls on every page load.

My questions is am I mis-understanding the use case somehow? Is it possible that it is being recommended to make a database type call on every request into a server for a given web page?

If the answer is yes, I assume the only way to fix this is to cache the user credentials, but from a security perspective, I really hate to cache credentials in general.

Thoughts?

// used to serialize the user for the session
passport.serializeUser(function(user, done) {
    done(null, user.id); 
   // where is this user.id going? Are we supposed to access this anywhere?
});

// used to deserialize the user
  passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user) {
      done(err, user);
    });
});

回答1:

In general, yes, you want to store user login state/session in database and fetch/update it with each incoming request as it is much more fault tolerant.

Assume that you don't have a database and you are storing the session on your web/app server and there might be many such servers serving the same website/app to handle the load. If one of your server fails, all your session data for all users that were served by that server is lost (there is yet another hassle with this approach - you need to make sure that one user is served by the same web/app server all the time as his/hers session is stored on that server - so you need to somehow handle session affinity/sticky sessions on your load balancer which is usually a pain, even impossible is some setups).

On the other hand, when you are storing sessions in a database, if one your servers fail, the data can be immediately retrieved by other servers from the DB (and you don't need to bind user to a particular server).

You may cache the data, let's say using Redis (or memcached), but then you need to make sure that the cache is not running on the same server as you app/web because you will face the same problem. (Redis is probably a better solution here as you can take a snapshot of it and quickly restore its data if node running it fails, you can't do that with memcached, at least not directly)

Generally, you want to store this kind of data in a DB that can handle this type of traffic well (eg. Mongo, DynamoDB, Redis) not in a relational database.

About the CND, in general, it will not offload much of the traffic from your DB (session storage) as you probably don't want to serve cached static content to just everyone. So you still need some kind of verification for which you need to make a request against your app server which will still query the DB to check whether a user is approved to request that static content, create a some kind of signed URL, send it to client and only after that the user can access the protected content from the CDN (but you can reuse that signed url if configured so, therefore it can help a bit).