带有 Passport-Local 和 deSerializeUser 问题的简单身份验证

Posted

技术标签:

【中文标题】带有 Passport-Local 和 deSerializeUser 问题的简单身份验证【英文标题】:Simple Auth With Passport-Local and deSerializeUser problem 【发布时间】:2019-06-06 19:40:48 【问题描述】:

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

Understanding passport serialize deserialize

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

【问题讨论】:

【参考方案1】:

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

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

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

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

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

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

【讨论】:

以上是关于带有 Passport-Local 和 deSerializeUser 问题的简单身份验证的主要内容,如果未能解决你的问题,请参考以下文章

使用passport-http Basic + passport-local组合时如何防止www-authenticate header

跨语言(python 到 scala)稀疏数据 ser/deser?

“passport”、“passport-local”和“passport-jwt”有啥区别? [关闭]

Gson自定义deseralizer,用于对象中的一个变量

Json Deseralizer 无法将字符串转换为 guid

在 node.js 中使用 passport-local 和 bcrypt 检查和更新密码