在Spring Application中注销时删除JWT

pra*_*nav 1 spring spring-security jwt spring-boot

我们正在尝试为基于Spring REST的应用程序遵循此代码库。 弹簧靴jwts

问题是我们无法从服务器注销期间删除JWT令牌。当我们在网上检查时,我们才知道唯一的解决方法是将此JWT令牌列入黑名单。是这样吗?

我们是基于令牌的身份验证的新手,请告诉我们是否存在诸如在注销调用中使令牌过期之类的解决方案。

Raf*_*Raf 5

长话短说short,您必须建立一种manually在注销时删除令牌或使令牌无效的机制。

我是否应该存储JWT令牌?


您应该问自己的问题是

  • 我是否需要将JWT令牌存储在数据库中?如果是这样,为什么?

上面的问题将不一定解决您的logout问题,因为您仍然需要一种机制来invalidate存储或不存储在中的令牌database

not storing数据库中令牌的好处之一是您无需担心deleting它们(无需维护或某些清理过程)

  • 他们令牌过期
  • 他们的范围改变
  • 用户的角色(万一发生password流量,我们别讨论其他flows角色),并且权限在数据库中已降级或升级,因此jwt中的内容已过时
  • 用户被删除
  • 用户已注销(如果这是删除令牌的足够充分的理由,那么会感到奇怪)
  • 令牌被盗用(整rick之一)
  • [添加其他案例]

验证令牌的有效性?


我确定您使用的是verify端点,其目的是验证令牌是否存在,valid但是不必检查上述所有情况,这意味着您必须

  • 自定义verify工作流程以添加更多custom checks
  • 在令牌verified用于signature validityexpiry time和其他令牌之前,default checks您可以自己运行custom checks,如果custom checks通过,则继续进行you shall not pass!

那您有什么选择呢?


好吧,除了blacklisting你可以做以下的事情

使用内存存储

只需将uniquely-identifying-metadataJWT令牌的密钥作为密钥存储到redis中,并为其提供一个expiry timeJWT令牌到期时间相同的时间,以便令牌到期self-destruct时使用。

set key {replace_with_jwt_unique_identifier} ex {jwt_expiry_timestamp}
Run Code Online (Sandbox Code Playgroud)

风险:Redis在内存中,并且条目不会保留。

使用数据库

不要使用Redis或不想冒险。您可以将数据库与自定义数据库表一起使用。一个单独的表是

  • 与JWT记录相关,并且具有 ON DELETE CASCADE
  • 与JWT记录无关,您必须自己维护

发出令牌时,也会填充此新数据库表。

其余常用步骤

normalJWT发出请求时,请使用JWT查询in-memory存储或database表以查看记录是否存在。如果有in-memory商店,简单的existence检查就足够了。如果database table您需要执行更多检查(即存在且未过期等),并且如果检查通过让请求通过,则否则you shall not pass!

当一个logout request进来时,在in-memory存储的情况下,只需删除key和继续(如果找到),在存储的情况下,database您可以删除JWT将级联到新表的记录。

何时进行自定义检查?

好吧,你可以做到

  • 首先,最重要的是使用自定义顶级过滤器或
  • 您可以扩展verify端点工作流来执行这些额外的检查

我使用的项目不需要使令牌失效,logout因此我不必跨过这座桥。我确实必须扩展verify端点以确保如果我的所有令牌custom checks都通过了,则令牌是有效的。

额外的阅读材料

除了您指出的教程。还有其他一些SO问题也讨论了类似的问题。看到

如果JWT被盗怎么办?
如何在注销时销毁JWT?
更多如何删除JWT令牌?
更改密码后
如何使JWT失效Github问题-如何使JWT 最终失效
最后一个最好的-失效JWT Web令牌


Ked*_*shi 4

我们遇到了类似的问题,并使用以下方法解决了它 -

  1. 我们向每个 JWT 令牌添加一个请求 ID 以及过期时间。
  2. 创建会话时,我们会根据其他令牌值及其到期时间将此请求 ID 保留在数据库中。
  3. 当服务器发起注销时,我们将此请求标记为过期。
  4. 下次如果使用相同的令牌,我们可以通过验证请求 ID 来确定这是一个过期的令牌。

现在,检查数据库中的请求 ID 成本很高,因此我们也使用内存缓存。