不使用黑名单的 JWT 注销功能?
JWT logout feature without using blacklist?
我以前用过JWT
,但他们API
不需要注销功能。
我需要为 android 应用程序的 API
和 SPA
实施注销功能。当我查找它时,我发现有两种方法可以做到这一点。
- 最简单的方法是从客户端删除
JWT Token
并收工。
这背后的逻辑是,由于服务器中没有维护任何类型的会话,删除客户端中的令牌应该就足够了。
但这仍然存在这样的可能性,即如果代币落入坏人之手,即使用户不再使用该代币,他们仍然可以使用它。
如果应用程序设计良好并使用 HTTPS
,那么发生这种情况的可能性非常低,并且可以通过保持令牌的有效时间短来最大限度地减少。但就我而言,令牌有效期为 30 天。
- 第二种选择是在服务器端维护一个令牌黑名单
这解决了即使在用户注销并停止使用后令牌仍然可用的问题。
但它增加了需要 运行 一个 cronjob
从黑名单 table 中删除过期令牌的复杂性。否则 table 最终会变得大得离谱。
它也有点破坏了使用 JWT
的意义。维护黑名单与维护会话非常相似。我们必须为每个请求 运行 一个额外的数据库查询。而且它的扩展性很差,因为没有。用户增长没有。需要列入黑名单的代币数量也会增加(对于像我这样的 API
拥有多个前端应用程序且代币有效期较长的 API
,这将是一个更大的问题。
然后我想到了第三种方式。
在存储随机生成的字符串的用户 table 中添加 jwt_secret
行。使用它来签署 JWT Token
然后在每个请求中使用 jwt payload
中的 user id
来获取用户表单 db(这不是额外的查询,无论如何我们都必须这样做)并验证使用用户 jwt_secret
的令牌签名。当用户注销时,我们更改 jwt_secret
这使得所有令牌都无用。
起初我认为这是一个很好的解决方案,只是意识到在此设置中,如果用户从一台设备或浏览器注销 he/she 会从所有设备注销。
那么还有其他选择吗?或修改上述任何一种方法来解决问题的方法。还是我想多了,应该使用上述选项之一?
对于注销,正如您指出的那样,这是用户发起的操作,我认为您不需要做任何额外的事情。如果用户以某种方式没有删除他的 JWT,那就这样吧。他不会获得任何额外的权限来访问他已经有权访问的内容。
但是,您的问题似乎暗示了如何知道 JWT 是否有效的问题。同样,正如您所指出的,如果 JWT 以某种方式落入坏人之手,那么可能无法避免这种情况。但是,对于每个请求,您通常会针对该 JWT 进行多种类型的验证,例如
- 检查 JWT 的声明,例如令牌到期日期
- 假设索赔通过,然后根据您的数据库检查该用户的 ID table 以确保该帐户处于活动状态,未被暂停等。
我的观点是,如果您需要在服务器端跟踪发生注销的情况,您可能需要将其保存到数据库中。但是,我认为您不需要这个。
我以前用过JWT
,但他们API
不需要注销功能。
我需要为 android 应用程序的 API
和 SPA
实施注销功能。当我查找它时,我发现有两种方法可以做到这一点。
- 最简单的方法是从客户端删除
JWT Token
并收工。
这背后的逻辑是,由于服务器中没有维护任何类型的会话,删除客户端中的令牌应该就足够了。 但这仍然存在这样的可能性,即如果代币落入坏人之手,即使用户不再使用该代币,他们仍然可以使用它。
如果应用程序设计良好并使用 HTTPS
,那么发生这种情况的可能性非常低,并且可以通过保持令牌的有效时间短来最大限度地减少。但就我而言,令牌有效期为 30 天。
- 第二种选择是在服务器端维护一个令牌黑名单
这解决了即使在用户注销并停止使用后令牌仍然可用的问题。
但它增加了需要 运行 一个 cronjob
从黑名单 table 中删除过期令牌的复杂性。否则 table 最终会变得大得离谱。
它也有点破坏了使用 JWT
的意义。维护黑名单与维护会话非常相似。我们必须为每个请求 运行 一个额外的数据库查询。而且它的扩展性很差,因为没有。用户增长没有。需要列入黑名单的代币数量也会增加(对于像我这样的 API
拥有多个前端应用程序且代币有效期较长的 API
,这将是一个更大的问题。
然后我想到了第三种方式。
在存储随机生成的字符串的用户 table 中添加 jwt_secret
行。使用它来签署 JWT Token
然后在每个请求中使用 jwt payload
中的 user id
来获取用户表单 db(这不是额外的查询,无论如何我们都必须这样做)并验证使用用户 jwt_secret
的令牌签名。当用户注销时,我们更改 jwt_secret
这使得所有令牌都无用。
起初我认为这是一个很好的解决方案,只是意识到在此设置中,如果用户从一台设备或浏览器注销 he/she 会从所有设备注销。
那么还有其他选择吗?或修改上述任何一种方法来解决问题的方法。还是我想多了,应该使用上述选项之一?
对于注销,正如您指出的那样,这是用户发起的操作,我认为您不需要做任何额外的事情。如果用户以某种方式没有删除他的 JWT,那就这样吧。他不会获得任何额外的权限来访问他已经有权访问的内容。
但是,您的问题似乎暗示了如何知道 JWT 是否有效的问题。同样,正如您所指出的,如果 JWT 以某种方式落入坏人之手,那么可能无法避免这种情况。但是,对于每个请求,您通常会针对该 JWT 进行多种类型的验证,例如
- 检查 JWT 的声明,例如令牌到期日期
- 假设索赔通过,然后根据您的数据库检查该用户的 ID table 以确保该帐户处于活动状态,未被暂停等。
我的观点是,如果您需要在服务器端跟踪发生注销的情况,您可能需要将其保存到数据库中。但是,我认为您不需要这个。