【问题标题】:How to properly use JTI claims with JWT to prevent replay attacks?如何正确使用 JTI 声明和 JWT 来防止重放攻击?
【发布时间】:2017-11-23 08:18:39
【问题描述】:

我使用 Spring 创建了一些 REST API,并使用 JWT 实现了 Spring Security 以进行身份​​验证。我的前端运行 AngularJs 并使用这些接收 JSON 响应的其余 API。 JWT 身份验证工作正常,但它允许将请求参数和标头从浏览器控制台简单地复制和粘贴到 Postman 或任何其他 REST 客户端,甚至可以从后端受保护的 API 获取成功的响应。

我正在尝试通过在 JWT 中使用 JTI 声明来解决此问题。我计划为每个请求后身份验证使用不同的 JTI 值,这样简单地从浏览器中窃取标头就行不通了。

现在在网上浏览了大量可用资源后,我仍然不清楚客户端或服务器应该在 JWT 中设置 JTI 值。

根据我的理解,如果我在服务器端执行此操作,我将不得不在每个响应中发送一个新的 JWT,并期望它在来自客户端的下一个请求中,同时在数据库中维护已用 JTI 的记录。但是,如果攻击者发现了这一点,他们只需使用前一个请求中的令牌,然后他们就可以轻松地与我的 API 进行交互。

另一方面,如果我在客户端执行此操作,我将不得不在 javascript 代码中保留 JWT 的秘密签名密钥和 JTI 生成逻辑,以便它可以附加 JTI 值并散列再次令牌。 那么我的问题是:

  1. 正确的实现方法是什么?我是否遗漏了什么或完全走错了方向?
  2. 我是否可以实施任何其他解决方案来禁止或取消验证来自非浏览器客户端的任何请求(在使用 Jsps 的旧 Spring MVC 应用程序中发生的方式)?

非常感谢任何帮助。卡在这上面很久了。

【问题讨论】:

标签: java angularjs spring spring-security jwt


【解决方案1】:

我无法谈论 Java/Spring,但我可以尝试澄清您对 JWT 和 JTI 声明的担忧。

实施 JTI 以唯一标识 JWT 有助于防止 replay attacks 攻击者发送相同的 JWT 以发出请求。服务器将生成 JTI 值并在每次响应时将其与新的 JWT 一起发送。当接收到一个新请求时,服务器必须验证 JTI 值(以确保它之前没有被使用过)。实现这一点确实需要在服务器上进行某种持久性存储,它看起来或多或少类似于传统会话,因此感觉有点奇怪,因为 JWT 的广告优势之一是“无状态应用程序”。

您对中间人攻击的担忧是绝对正确的:如果有人拦截了 JWT(及其一次性 JTI),然后在您之前提出请求,他们的请求将被考虑有效并且您的后续请求将在服务器看来是“重播”(服务器会认为它们无效)。

【讨论】:

  • 这是否意味着使用 JTI 的唯一好处是更少的存储空间?保存 JTI 字符串并检查它们是否已发布,而不是检查整个令牌。
  • 不,在您的 JWT 上实施唯一标识符 (JTI) 的好处是安全方面的好处 - 实施正确创建、存储和检查 JTI 的系统需要更多资源/存储,因为适当的实现将为使用每个 JWT 发出的每个请求创建一个新 ID。系统不仅可以判断 JWT 是否有效,还可以判断 JWT 以前是否曾被使用过。
  • 我认为 C.M.意思是您可以将 JWT 本身存储在数据库(或其他东西)中以记录它是否曾经见过,但也许我错过了一些东西。
猜你喜欢
  • 2015-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多