如何正确使用JTI声明JWT以防止重放攻击?

时间:2017-06-20 16:54:12

标签: java angularjs spring spring-security jwt

我使用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应用程序中发生的方式)?
  3. 非常感谢任何帮助。现在已经坚持了很长时间。

1 个答案:

答案 0 :(得分:5)

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

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

你对中间人攻击的关注是绝对正确的:如果有人拦截JWT(及其一次性使用的JTI)然后在你做之前提出请求,他们的请求将会被视为有效,您的后续请求将显示给服务器"重播" (并且服务器会认为它们无效)。