如何安全地重试失败的jQuery ajax POST请求?

时间:2015-08-12 16:41:14

标签: jquery ajax rest post idempotent

在RESTful架构中,POST请求既不是安全也不是 Idempotent

现在,jQuery的ajax调用允许重试失败的请求,方法是设置ajax调用以使用error函数来捕获失败,并可选择重试调用(以及{{1}等相关设置}},timeouttryCountretryAfter)。

重试GET调用不是问题(因为它们都是安全幂等),但是如何重新启动POST调用呢?

例如,假设我们使用ajax POST来插入新记录:

  1. 在客户端上启动ajax POST调用。
  2. 服务器收到呼叫,更新数据库。
  3. 服务器响应,但此响应无法传递给客户端。
  4. 因此客户端认为发生了故障,并重试了呼叫。
  5. 服务器再次接收呼叫,进行另一次更改。
  6. 依旧......
  7. 迎合这种情况的最佳方式是什么?

1 个答案:

答案 0 :(得分:2)

您的代码可以轻松休息的唯一方法(原谅双关语)是确认数据已被接收和接受。

所以答案实际上取决于POST的性质。如果POST确实是更新,例如将名称设置为" John",那么您可以安全地重试几次,直到您得到确认。

但是,你所说的情况是POST在REST意义上真的是一个POST,通常意味着它会添加一个新行。在这种情况下,正确的方法取决于客户端和服务器之间更深层次的握手。

最后,数据完整性是处理数据库的代码的工作,因此服务器代码。因此,如果不应重复行,则方案将按如下方式进行:

  • 客户端为"提交令牌"进行GET,包括客户端生成的ID。
  • 服务器根据clientID生成提交令牌,并将其存储在表
  • 服务器将令牌发送到客户端
  • 客户提交包含令牌的POST。
  • 服务器接收令牌,验证它,插入帖子,并成功响应

    1. 因此,如果GET令牌请求未进入服务器,则客户端可以再次请求,始终使用相同的clientID。
    2. 如果客户端最终获回一个令牌,他可以假设服务器有他的请求记录,并期待后续POST。
    3. 如果客户端在几次失败后最终获得了多个令牌响应,则它们都将是相同的令牌。
    4. 然后客户端将POST,并继续发布(使用令牌),直到他收到成功
    5. 如果服务器获得其中一个帖子,它将插入数据并使令牌无效并响应成功。
    6. 如果服务器收到请求并且已经使用了令牌,则会以#34;重复请求回复"
    7. 客户端只能获得1"成功",如果客户端碰巧没有收到它,那么在将来的尝试中它将获得"重复请求"并且知道它已被插入。

现在,如果服务器不关心重复项并且您无法控制它,并且它只是客户端,那么最好的解决方案就是等待很长时间才能再次尝试,总是替代得到和发布。理论上你不可能知道,因为他们可能有一个队列在服务器离线时收集请求,下周他们会处理它们。