提问者:小点点

带Passport-Local和反序列化用户的简单身份验证问题


在阅读了这里关于反序列化和序列化用户如何在Passport流中工作的精彩描述之后

了解passport序列化反序列化

我关心的是对每个请求都调用deSerializeUser对性能的影响。我见过的所有示例(见下面的示例)都是deserializeUser调用类似于数据库的内容来完成这项工作。假设您没有为所有资产使用cdn,这意味着每次页面加载时都会调用许多数据库。

我的问题是我是否误解了用例?有没有可能建议对给定网页的每个服务器请求进行数据库类型调用?

如果答案是肯定的,我假设修复这个问题的唯一方法是缓存用户凭据,但从安全角度来看,我通常确实讨厌缓存凭据。

思想?

// 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个答案

匿名用户

一般来说,是的,您希望在数据库中存储用户登录状态/会话,并在每个传入请求中提取/更新它,因为它的容错性要强得多。

假设您没有数据库,将会话存储在Web/App服务器上,并且可能有许多这样的服务器为同一个Website/App提供服务,以处理负载。如果您的一台服务器出现故障,那么由该服务器提供服务的所有用户的所有会话数据都会丢失(这种方法还有一个麻烦--您需要确保一个用户始终由同一个Web/App服务器提供服务,因为他/她的会话存储在该服务器上--因此您需要在负载均衡器上处理会话关联/粘滞会话,这通常是一个麻烦,甚至有些设置是不可能的)。

另一方面,当您在数据库中存储会话时,如果您的一个服务器出现故障,其他服务器可以立即从数据库中检索数据(并且您不需要将用户绑定到特定的服务器)。

您可能会缓存数据,比如使用Redis(或memcached),但是您需要确保缓存不是运行在与您的App/Web相同的服务器上,因为您将面临同样的问题。(Redis可能是一个更好的解决方案,因为如果运行它的节点出现故障,您可以拍摄它的快照并快速恢复它的数据,但使用memcached不能这样做,至少不能直接这样做)

通常,您希望将这类数据存储在能够很好地处理这类流量的DB中(例如Mongo,DynamoDB,Redis),而不是存储在关系数据库中。

关于CND,一般来说,它不会从您的DB(会话存储)中卸载很多流量,因为您可能不想只为每个人提供缓存的静态内容。因此,您仍然需要某种验证,您需要针对您的应用程序服务器发出请求,它仍然会查询DB以检查用户是否被批准请求该静态内容,创建某种签名URL,将其发送到客户端,并且只有在此之后,用户才能从CDN访问受保护的内容(但是,如果配置为这样,您可以重用该签名URL,因此它会有所帮助)。