在这里阅读了有关在Passport流中反序列化和序列化用户工作方式的出色描述
Understanding passport serialize deserialize
我担心在每个请求上调用deSerializeUser对性能的影响。我所见过的所有示例(请参见下文)都具有deserializeUser调用看起来像数据库User.findById
的对象来完成该工作。假设您没有对所有资产使用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);
});
});
答案 0 :(得分:1)
通常,是的,您希望将用户登录状态/会话存储在数据库中,并随每个传入请求获取/更新它,因为它具有更高的容错能力。
假定您没有数据库,并且正在将会话存储在Web /应用程序服务器上,并且可能有许多此类服务器在同一个网站/应用程序中处理负载。如果您的一台服务器发生故障,则该服务器所服务的所有用户的所有会话数据都会丢失(这种方法还有另一个麻烦之处-您需要确保一个用户由同一台Web /应用服务器服务)他/她的会话存储在该服务器上的时间-因此,您需要以某种方式在负载均衡器上处理会话关联性/粘性会话,这通常很麻烦,有些设置甚至是不可能的)。
另一方面,当您在数据库中存储会话时,如果一台服务器发生故障,则其他服务器可以立即从数据库中检索数据(并且不需要将用户绑定到特定服务器) 。
您可以缓存数据,比方说使用Redis(或memcached),但是随后您需要确保缓存不在与您的应用程序/ Web相同的服务器上运行,因为您将面临相同的问题。 (Redis可能是一个更好的解决方案,因为您可以对其进行快照并在运行它的节点失败时快速还原其数据,您不能使用memcached做到这一点,至少不能直接这样做)
通常,您希望将这类数据存储在可以很好地处理这种流量的数据库中(例如Mongo,DynamoDB,Redis),而不是关系数据库中。
关于CND,通常,它不会从数据库(会话存储)中卸载大量流量,因为您可能不想仅向所有人提供缓存的静态内容。因此,您仍然需要某种验证,需要针对您的应用服务器发出请求,该服务器仍将查询数据库以检查用户是否被批准请求静态内容,创建某种签名的URL并将其发送到客户端,只有在此之后,用户才能从CDN访问受保护的内容(但如果已配置,则可以重用该签名的url,因此可以有所帮助)。