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