首页 > 解决方案 > 带有 Passport-Local 和 deSerializeUser 问题的简单身份验证

问题描述

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

了解护照序列化反序列化

我担心在每个请求上调用 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);
    });
});

标签: node.jspassport.jspassport-local

解决方案


一般来说,是的,您希望将用户登录状态/会话存储在数据库中,并随每个传入请求获取/更新它,因为它具有更高的容错性。

假设您没有数据库,并且您将会话存储在您的 Web/应用程序服务器上,并且可能有许多这样的服务器为同一个网站/应用程序提供服务来处理负载。如果您的一个服务器发生故障,则该服务器所服务的所有用户的所有会话数据都将丢失(这种方法还有另一个麻烦 - 您需要确保一个用户由同一个 Web/应用程序服务器提供服务他/她的会话存储在该服务器上的时间-因此您需要以某种方式处理负载均衡器上的会话亲和性/粘性会话,这通常很痛苦,甚至有些设置是不可能的)。

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

您可以缓存数据,比如说使用 Redis(或 memcached),但是您需要确保缓存不在与您的应用程序/Web 相同的服务器上运行,因为您将面临同样的问题。(Redis 在这里可能是一个更好的解决方案,因为您可以对其进行快照并在运行它的节点失败时快速恢复其数据,您不能使用 memcached 做到这一点,至少不能直接这样做)

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

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


推荐阅读