2017-02-03 40 views
0

我正在使用JWT进行身份验证。但是,我不希望用户从多个设备登录。我如何确保这一点?只允许在NodeJS中一次从一台设备登录

现在 - 我所能想到的是将JWT存储到数据库中,然后检查它是否存在。如果存在,那么它的生成时间是多少。如果时间过长 - 我们将重新生成令牌并将其传递回第二台设备。

+0

我不认为你想在你的数据库中保存JWT令牌,而只是该用户已经登录并且他们上一次活动的时间。在这里,给定用户的所有JWT令牌都不相同(因为他们可能有时间相关的信息),所以你不需要查找JWT令牌的完全匹配 – jfriend00

+0

我也认为你可能有注销问题,因为如果当新客户想要登录时,您想要强制之前的用户注销,您必须以某种方式r保留其JWT令牌不再有效的信息。这可能是JWT的服务器无状态本质不能帮助您的情况。使用传统的会话方案,您只需删除服务器上的用户会话对象以将其注销。 – jfriend00

+0

@ jfriend00由智威汤逊生产的一个字段在有效载荷中称为iat。这实际上有时间信息 –

回答

0

这几乎是你唯一的选择,JWT的目的非常无状态。类似于你不能真正做一个服务器端注销没有类似的技术

正如jfriend指出,单独存储JWT是不够的。你需要做的是确保下一次用户请求登录时,他们还没有发布给他们未到期的JWT。

经历了完整的流程:

案例1:用户不中的任何地方登录。在这种情况下,JWT被发布和存储。可能在用户记录中以便于检索。

情况2:用户尝试登录其他设备。无论您是让他们明确注销第一台设备还是为他们做这些,您现在都必须将存储的令牌发送到撤销令牌列表。在确定令牌是否有效时,您的令牌验证逻辑将不得不考虑该列表。

/*进一步澄清*/

我觉得好像有点详细可能是有用的人,所以我要进入执行了一下。

**身份认证的请求**

这应该不会改变,但它是值得一提的是,我假设您有需要身份验证不包括积极和有效的智威汤逊的路线,并要求这些路线被401拒绝(并可能提供URL到登录网址)。

登录

登录逻辑总是包括用户查找,所以如上所述,在此应用程序的流程应该包括查找,但在应用程序将用户登录之前,你会检查,看看是否已经存在为用户分配的令牌未过期。

如果没有已分配给该用户的令牌,则检查凭据(无论您通常会这么做),生成JWT(带有exp标题以指示有效负载中的过期时间),将该令牌重新保存回用户文档/记录以备将来参考。

如果有分配的令牌,该令牌也未到期,那么你要么必须注销用户其他设备的(更多的在第二),并且在当前的设备登录他们,要不然您必须拒绝登录尝试,并让该人员退出新设备。我认为前一种方法更加用户友好,但这取决于您的应用程序的需求。

注销

随着JWT,以保证用户的唯一方法是不能使用的发出令牌要么包括在有效载荷中的期满时间(EXP),并使用该检查该验证器,或者在服务器上知道哪些令牌不再有效并检查它们。最健壮的解决方案都可以。

所以,假设你已经处理过期了,显式的注销功能将通过在某处创建一个被撤销的标记列表来处理。例如,如果您使用的是MongoDB,您需要创建一个集合来存储这些集合。理想情况下,您还可以在每个到期日期后的某个点设置一个TTL,这样Mongo就会驱逐无论如何过期的令牌,以节省您的时间和空间。

如果您正在对新的登录请求执行自动注销,那么当您将新令牌保存在用户文档中时,您会按照此逻辑将旧令牌放入撤销令牌列表。

注销路由也应该由经过身份验证的用户访问,以便在需要时显式注销,而不管您是否执行自动注销。

验证请求,

此时,您应该相当肯定的是,用户只能在一个设备上登录。但是,您还需要确保它们没有试图用撤销的令牌发出请求。

然后,您的通用路由安全中间件还需要检查已吊销的标记列表,以检查客户端提供的标记是否在所述列表上,然后检查以确保它未到期(因为可以在验证时检查到期时间,保存到DB的往返行程