java – 如何正确使用JTI声明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值并再次散列令牌.
我的问题是:

>实现这个的正确方法是什么?我错过了什么或完全走错了方向吗?
>我是否可以实现任何其他解决方案来禁止或取消认证来自非浏览器客户端的任何请求(使用Jsps的传统Spring MVC应用程序中发生的方式)?

任何帮助都非常感谢.现在已经坚持了很久.

解决方法

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

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

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

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...