java - 如何正确使用 JTI 声明和 JWT 来防止重放攻击?

标签 java angularjs spring spring-security jwt

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

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

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

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

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

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

非常感谢任何帮助。长期以来一直坚持这一点。

最佳答案

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

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

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

关于java - 如何正确使用 JTI 声明和 JWT 来防止重放攻击?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44658963/

相关文章:

Java : No matter which method I use, 我无法将 double 四舍五入到小数点后 4 位

angularjs - 如何在 Jasmine 中重现 "10 $digest() iterations reached. Aborting"错误

javascript - 函数内 Restangular 的 jasmine 测试用例

Spring 表单验证 : Whitelabel Error Page

java - 使一个类成为 Mockito 模拟而不调用模拟

java - 如何在 Java 中同步运行一个进程?

java - 使用 java 将文件上传到由 ADFS SSO 验证的 Sharepoint Online 存储库?

javascript - 检查网络并处理空错误对象

java - Spring REST 模拟上下文路径

java - 在类中转换枚举