仅允许一次在NodeJS中从一台设备登录 [英] Only allow signing in from one device at a time in NodeJS

查看:422
本文介绍了仅允许一次在NodeJS中从一台设备登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用JWT进行身份验证.但是,我不希望用户从多个设备登录.我该如何确保?

I am using JWT for authentication. However I do not want the user to be logged in from multiple devices. How do I ensure this?

现在-我所能想到的就是将JWT存储到DB中,然后检查它是否存在.如果存在的话,它是在什么时候生成的.如果时间太多-我们要重新生成令牌,然后传回第二台设备.

Right now - All I can think of is to store the JWT into DB and then check if it exists . And if it exists, what was the time it was generated at. If too much time - we go and regenerate the token and pass on back to the 2nd device.

推荐答案

这几乎是您唯一的选择,JWT故意是无状态的.类似于没有类似技术就无法真正注销服务器端的方法

That's pretty much your only option, the JWT is pretty stateless on purpose. Similar to how you can't really do a server side logout without similar technique

正如jfriend指出的那样,仅存储JWT是不够的.您需要做的是确保用户下次请求登录时,没有向他们发出未到期的JWT.

As jfriend points out, storing the JWT alone is insufficient. What you need to do with it is ensure that the next time a user requests login, that they don't already have an unexpired JWT issued to them.

仔细检查流程以确保完整性:

Going through the flow for completeness:

情况1:用户未登录任何地方.在这种情况下,将发布并存储JWT.可能在用户记录中以便于检索.

Case 1: User isn't logged in anywhere. In this case, JWT is issued and stored. Possibly in the user record for easy retrieval.

情况2:用户尝试登录另一台设备.无论您是让它们明确退出第一台设备还是为它们注销,现在都必须将存储的令牌发送到已撤销令牌的列表中.在确定令牌是否有效时,您的令牌验证逻辑将必须考虑该列表.

Case 2: User tries to log in on another device. Whether you make them explicitly log out of the first device or do it for them, you have to now send that stored token into a list of revoked tokens. Your token validation logic will have to take that list into account when determining if a token is valid or not.

/*进一步说明*/

我觉得更多细节可能对人们有用,因此我将进行一些实施.

I feel like a bit more detail might be useful for folks, so I'm going to go into implementation a bit.

**未经身份验证的请求**

** Unauthenticated requests **

这应该不会改变,但是值得一提的是,我假设您具有需要身份验证的路由,并且对那些不包含有效和有效JWT的路由的请求将被401拒绝(并且可能会提供URL到登录网址).

This shouldn't change, but it's worth mentioning that I'm assuming you have routes that require authentication, and requests to those routes which do not include an active and valid JWT get rejected with a 401 (and probably provided the URL to the login url).

登录

登录逻辑始终包括用户查找,因此,如上所述,此应用程序中的流程应包括该查找,但是在将用户登录到应用程序中之前,您将检查是否已经为该用户分配了已分配的令牌.没有过期.

Login logic always includes a user lookup, so as described above, the flow in this application should include that lookup, but before logging the user in the application you will check to see if there's already an assigned token to the user which has not expired.

如果没有分配给用户的令牌,则通常检查凭证,然后生成一个JWT(其exp标题指示有效载荷中的到期时间),然后将该令牌保存回用户文档/记录中备查.

If there is not a token already assigned to the user, then check credentials however you normally would, generate a JWT (with an exp heading to indicate expiration time in the payload), save that token back in the user document/record for future reference.

如果有一个 令牌也未过期,那么您要么必须将用户注销到另一台设备上(稍后再进行介绍),然后将其登录到当前设备中设备,否则您必须拒绝登录尝试并使该人退出新设备.我认为前一种方法对用户更友好,但这取决于您应用程序的需求.

If there is an assigned token which is also unexpired, then you either have to log the user out of the other device (more on that in a second), and log them in to the current device, or else you have to reject the login attempt and keep the person logged out of the new device. I think the former approach is more user friendly, but it depends on the needs of your application.

注销

使用JWT时,确保用户无法使用已发行令牌的唯一方法是在有效载荷中包含到期时间(exp),并使用验证程序进行检查,或者在服务器上知道哪些令牌不再有效,请与他们核对.最强大的解决方案可以同时做到.

With JWT, the only way to guarantee a user is unable to use an issued token is to either include an expiration time (exp) in the payload, and use a verifier that checks that, or to know on the server which tokens are no longer valid and check against them. The most robust solutions do both.

因此,假设您已经在处理到期,则可以通过在某处创建吊销的令牌列表来处理显式注销功能.例如,如果您使用的是MongoDB,则将创建一个集合来存储它们.理想情况下,您还应该为每个设置为TTL的TTL设置有效期后的某个时间点,以便Mongo逐出本应过期的令牌,以节省时间和空间.

So, assuming you're handling the expiration already the explicit logout feature would be handled by creating a revoked tokens list somewhere. If you're using MongoDB, for example, you'd create a collection to store those. You'd ideally also set a TTL on each one that is set to some point after the expiration date, so that Mongo will evict tokens that are otherwise expired anyway, to save yourself time and space.

如果您要对新的登录请求进行自动注销,则在您将新令牌保存在用户文档中时,将按此逻辑将旧令牌放入已撤销的令牌列表中.

If you're doing the auto-logout on a new login request, you'll hit this logic to place the old token into the revoked tokens list when you save the new token in the user's document.

经过身份验证的用户也应该可以到达注销路由,以明确注销他们是否愿意,无论您是否进行自动注销.

The logout route should also be reachable by authenticated users, to explicitly logout if they want, regardless of whether you do the auto logout or not.

已认证的请求

此时,您应该合理地确定用户只能在一个设备上登录.但是,您还需要确保他们没有尝试使用已撤销的令牌发出请求.

By this point you should be reasonably certain that users can only login on one device. However, you also need to make sure that they aren't trying to make a request with a revoked token.

然后,您的通用路由安全中间件将还需要检查已吊销的令牌列表,以在检查以确保客户端提供的令牌没有过期之后查看该列表中是否包含客户端提供的令牌(因为可以在验证后检查过期时间,保存到数据库的往返.

Your generalized route security middleware would then need to also check the revoked token list to see if the token offered by the client is on said list after checking to make sure it's not expired (since the expiry can be checked upon validation, saving a round-trip to the DB.

这篇关于仅允许一次在NodeJS中从一台设备登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆