我正在使用 JWT 进行身份验证。但是我不希望用户从多个设备登录。我如何确保这一点?
现在 - 我能想到的就是将 JWT 存储到数据库中,然后检查它是否存在。如果它存在,它是在什么时间生成的。如果时间太长 - 我们会重新生成 token 并传递回第二个设备。
最佳答案
这几乎是您唯一的选择,JWT 是故意无状态的。类似于如果没有类似的技术,您将无法真正进行服务器端注销
正如 jfriend 所指出的,单独存储 JWT 是不够的。您需要做的是确保下次用户请求登录时,他们还没有向他们发出未过期的 JWT。
遍历流程以确保完整性:
情况 1:用户未在任何地方登录。在这种情况下,JWT 被发布和存储。可能在用户记录中以便于检索。
情况 2:用户尝试在另一台设备上登录。无论您是让他们明确退出第一个设备还是为他们做这件事,您现在都必须将存储的 token 发送到已撤销的 token 列表中。在确定 token 是否有效时,您的 token 验证逻辑必须考虑该列表。
/* 进一步澄清 */
我觉得更多的细节可能对人们有用,所以我将深入实现。
** 未经身份验证的请求 **
这不应该改变,但值得一提的是,我假设您有需要身份验证的路由,并且对那些不包含事件和有效 JWT 的路由的请求会被 401 拒绝(并且可能提供了登录的 URL网址)。
登录
登录逻辑始终包括用户查找,因此如上所述,此应用程序中的流程应包括该查找,但在将用户登录到应用程序之前,您将检查是否已经为用户分配了未过期的 token 。
如果没有已分配给用户的 token ,则按照通常情况检查凭据,生成 JWT(带有 exp 标题以指示有效负载中的到期时间),将该 token 保存回用户文档/记录以备将来引用.
如果分配的 token 也未过期,则您必须将用户从其他设备注销(稍后将详细介绍),然后将其登录到当前设备,否则您必须拒绝登录尝试并让此人退出新设备。我认为前一种方法对用户更友好,但这取决于您的应用程序的需求。
登出
使用 JWT,保证用户无法使用已发布 token 的唯一方法是在有效负载中包含到期时间 (exp),并使用验证器进行检查,或者在服务器上了解哪些 token 不再是有效并检查它们。最强大的解决方案可以做到这两点。
因此,假设您已经在处理过期,显式注销功能将通过在某处创建一个已撤销的 token 列表来处理。例如,如果您使用 MongoDB,您将创建一个集合来存储这些。理想情况下,您还应该为每个设置为过期日期后某个时间点的 TTL 设置一个 TTL,以便 Mongo 将驱逐无论如何已过期的 token ,以节省您的时间和空间。
如果您对新的登录请求执行自动注销,当您将新 token 保存在用户文档中时,您将点击此逻辑将旧 token 放入已撤销的 token 列表中。
注销路由也应该可以由经过身份验证的用户访问,如果他们愿意,可以明确地注销,无论您是否执行自动注销。
经过身份验证的请求
至此,您应该可以合理地确定用户只能在一台设备上登录。但是,您还需要确保他们没有尝试使用已撤销的 token 发出请求。
然后,您的通用路由安全中间件还需要检查已撤销的 token 列表,以查看客户端提供的 token 是否在检查以确保未过期后是否在所述列表中(因为可以在验证时检查是否过期,从而节省了一轮-去数据库旅行。
关于node.js - 在 NodeJS 中一次只允许从一台设备登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42028920/