我在客户端存储会话/本地存储上的令牌。我面临的问题是,一旦用户复制该令牌并将其用于其他已登录的会话服务,它就可以在JWT上返回无效令牌。 varify。
用户退出后,有Blacklist/Delete/Expire
目前使用的令牌吗?
答案 0 :(得分:4)
有几种方法可以为此目的设置黑名单:
1)(数据库中的黑名单用户)为用户添加数据库列isTokenExpired,并在成功登录时将其设置为false,如果要使令牌过期,则为true(例如,用户更改密码,注销或足够的时间已过期。
上述方法将达到您的目的,但我觉得这是对编程的侮辱。我假设您正在使用JWT,以便用户不必每次都登录,并且您只有一台服务器正在进行身份验证和所有其他服务器功能。虽然JWT不是为#34;会话"而设计的,但为此目的使用JWT可以减轻数据库的负担。但是,如果您在每个用户操作上设置并检查另一个数据库标志,那么您将再次添加该负载,并且您仍然拥有与JWT等相关联的所有负载,因此您可能只需对每个用户操作重新进行身份验证。
2)(将用户/服务器RAM中的令牌列入黑名单)当我为自己研究此问题(如何使个别令牌无效)时,我找到了一些解决方案,其中服务器维护白名单或RAM中的黑名单,因此无需添加数据库或文件加载。这可能是一个更好的解决方案,但我不记得任何促进这一点的库的名称。也许其他人可以提及其中一些。
3)将令牌设置为非常短的到期时间(例如60秒或5分钟)并设置客户端以自动请求每个令牌(~55秒或~4分钟50)秒)。然后,服务器将以与我现在假设您正在执行此操作的方式相同的方式检查和验证令牌,而无需访问数据库,然后将为所有其他字段生成具有相同值的新令牌,但使用新的&#34 ;到期时间"值,并将该令牌发送回客户端,在那里它将用这个新的JWT替换它的JWT,并重新启动它的5分钟计时器。这是其他选择之间的良好平衡,并保持使用JWT的一些好处,但确实增加了一些小成本。我认为对于许多应用程序来说这是一个非常好的解决方案,但它肯定取决于具体的应用程序,但它有点hacky并且绝对不是"正确的方式"这样做。
4)使用JWT +会话这是"正确的方式"去做吧。在我很久以前的研究之后,我意识到 JWT并不是用来维护会话的:JWT只是表示声明的安全方式。想象一下,拥有一个拥有数千万用户的大型系统,您需要世界各地的许多服务器。您可能拥有3个身份验证服务器(在美国,澳大利亚,英国)。然后,用户将其用户名和密码发送到认证服务器,其中将在数据库中检查详细信息,如果有效,将发送JWT。您可能还有10多个常规服务器来处理您的API。然后,客户端将使用其JWT向API服务器发出每个请求。 API服务器将拥有身份验证服务器用于生成JWT的密钥副本,并将验证您的声明。您的声明是"我已通过身份验证"。然后,此API服务器将生成一个会话,客户端将被"登录"。 JWT可能会在5分钟后过期。如果用户在这5分钟内没有登录,他们将无法登录。如果用户登录,他们将登录,直到API服务器将其启动。每当发生导致您想要踢用户的事情时,API服务器都可以关闭会话。即使对于单服务器应用程序,这仍然是正确的方法。 JWT不适用于会话,你(正如我所做的)开始注意到这些看似无法解决的问题,因为你正在使用JWT进行会话。
无论如何,我推荐3或4,这两个选项都有许多应用的净正值。
1和2似乎比他们提供的好处产生更多问题。
但当然,它总是取决于应用程序。如果您只是以5美元的价格在fiverr上制作一些网站,那么就做任何事,你知道我的意思吗?
如果有更好的解决方案,我也有兴趣知道!请记住,JWT代表索赔,并准确考虑客户所代表的索赔。
答案 1 :(得分:1)
回答您的第一个问题(JWT存储在服务器Node.js中)
JWT令牌未存储在服务器端。它是一种基于身份验证系统的签名(通过密钥,RFC 7519)。
因此服务器只是验证令牌,如果验证了令牌,那么它就可以访问用户,因此任何拥有令牌的用户都可以像你一样。
例如 - 您可以复制登录的Facebook用户的cookie /存储,然后转到另一个浏览器并设置这些cookie /存储。您将以该用户身份登录一些。
FYI @safebookverified第三种方式主要用于。感谢。