我们当前的应用程序使用HTTP会话,我们希望将其替换为JWT。
设置只允许每个用户使用一个会话。这意味着:
这是有效的,因为会话ID和用户ID之间存在服务器端关系。
使用JWT我可以想象在用户数据库中有一些计数器,每次登录都会增加,即:
现在每次请求都要检查传入签名是否与当前计数器值相符。
这以某种方式使其有状态。 :(
但是...... JWT的一个好处是,无需访问任何数据库或会话存储来验证令牌。
还有其他一些防止并发登录的解决方案吗?也许某些东西在没有数据库访问的情况下工作并保持无状态?
答案 0 :(得分:3)
你非常接近解决方案。
为此,您需要以下内容:
1.在令牌中包含iat(发出令牌的时间)
2.某处存储用户上次登录的时间,例如用户的个人资料。
现在验证令牌时,请进行额外检查:iat(Issued At)必须等于或晚于上次登录时间。这隐含地使较旧的令牌无效。
答案 1 :(得分:1)
关闭其他任何设备上的用户会话怎么办?
怎么样。每次用户登录时,您是否按设备类型保存上一次登录,并向所有连接的相同类型的设备(假定是一个)发送推送通知?
在这种情况下,您可以在浏览器上向该浏览器发送推送通知,只需检查一下当前关闭该浏览器会发生什么情况?
对于移动应用程序,您可以向移动应用程序发送推送通知,并带有关闭指令
答案 2 :(得分:0)
这是另一种解决方案,在某些情况下可能更合适。
您仍然需要进入数据库,但是假设大多数用户只有一个设备,而只有一些用户有第二个设备,则可以使用以下策略:
在登录期间(新令牌请求),客户端可以提供设备ID。将此与用户的“ last_device”值进行比较。如果不同,则意味着用户已更改为新设备。
发生这种情况时,请在特殊表中为此用户添加一个epoc条目。
userid
:唯一参考用户(id)不能为空
epoc
:时间戳
这个想法是,该表可能比完整的用户表小得多。只有最近登录了多个设备的用户才能在此表中拥有一个条目。因此,扫描此表是有效的。在以正常方式验证令牌之后,请检查iat(发行位置)是否不在用户会话开始之前。如果是,则该设备不是最新登录的设备。
此解决方案还有其他用途:它允许用户远程注销自己(您可以使用当前时间为该用户创建一个新条目,从而有效地使他们的所有现有令牌失效)。
通过定期删除早于任何令牌的最大生存期的项目来维护此表。
答案 3 :(得分:0)
首先,在使用JWT进行会话时,定义以下内容很重要:
如果您使用有状态解决方案来使令牌无效,则可以在数据库中查询该用户的最后一个会话ID,并与接收到的令牌进行比较。
正如其他答案所指出的,在无状态解决方案中,您可能需要将状态保持在某个地方。但是与有状态令牌相比,您只需要存储建议的计数器或“ @The Tahaan建议的” last_login。
如果您觉得使用数据库太重了,我建议您使用Redis之类的内存解决方案,该解决方案除了速度非常快之外,还可以轻松设置持久数据的持续时间。这样,如果出现以下情况,用户将不得不再次登录:
答案 4 :(得分:0)
我认为该怎么做。 只需创建一个随机id(让它称为验证代码)并在生成jwt时将其存储在DB中即可。 在JWT中进行编码。 每当使用jwt发出任何请求时,请检查以jwt编码的验证代码在DB中是否匹配。 如果用户尝试登录到其他设备,它将重新生成验证码,并终止所有其他会话。