Web项目如何防止客户端重复发送请求

在Web项目中,有一些请求或操做会对数据产生影响(好比新增、删除、更新),针对这类请求通常都须要作一些保护,以防止用户有意或无心的重复发起这样的请求致使的数据错乱。前端

本文总结了一些防止客户端重复发送请求的方法。ajax

方法一:JS监听Form的onsubmit事件

在经典场景下,浏览器经过Form发送请求。所以只须要在Form onsubmit时将Submit按钮disable,就可以防止用户双击致使的重复请求(这种问题通常发生在年纪大的用户身上,他们分不清单击和双击)。数据库

可是随着前端的发展,Form之外的请求方式也愈来愈多,好比利用各类前端框架(Vue、AngularJs、Backbone等)写的App,他们更多的采用的是ajax的方式和后端交互。那么前端开发人员必须在开发时针对每一个表明发起请求的UI元素作处理,像Form同样,在发起请求的时候把相关UI元素禁用掉。json

而有些交互方式则可能连表明发起请求的UI元素都没有,好比Segmentfault的markdown编辑器就是在一边输入的时候一边保存的。那么这时就须要前端代码采用其余手段来控制重复请求的发生。后端

优势:浏览器

  1. 不须要后端写代码

缺点:前端框架

  1. 不存在统一的解决方案,必须针对每种状况写处理代码
  2. 没法控制浏览器刷新发起的重复请求
  3. 前端开发人员忘记写相关代码
  4. 没法控制恶意的重复请求,好比绕过浏览器直接发起

方法二:Http Status Code 302(后端重定向)

服务端采用重定向的方式,防止用户刷新浏览器发出重复请求。这是比较经典的后端控制重复请求的方式,由于一旦重定向成功后,用户刷新浏览器所刷新的是那个重定向地址,而不是数据操做地址。服务器

优势:markdown

  1. 不须要写前端代码

缺点:cookie

  1. 在还未响应302以前,所发起的重复请求,好比:用户快速的双击、刷新浏览器
  2. 在某些前端程序里(好比SPA),不能使用重定向
  3. 后端开发人员忘记写相关代码
  4. 没法控制恶意的重复请求,好比绕过浏览器直接发起

方法三:结合方法一和方法二

结合方法一和方法二的话却是能够解决大部分问题,可是解决不了如下问题:

  1. 在还未响应302以前,用户刷新浏览器致使的重复请求
  2. 有些场景下压根不能使用重定向
  3. 前、后端开发人员忘记写相关代码
  4. 没法控制恶意的重复请求,好比绕过浏览器直接发起

方法四:token方式

token的流程是这样的:

  1. 在浏览器发送请求前,先到服务端索要token
  2. 浏览器发送请求时,将token一并提交
  3. 服务端检查请求是否携带token、token是否有效(好比是否正确、是否过时)。若是不正确则响应失败;若是正确则销毁token,继续业务逻辑。

关键点在于:

  1. 每一个token都是一次性且有过时时间的,可以防止token前端代码bug形成的重复利用和无限利用。
  2. 服务器要求请求必须携带token,可以避免前端开发人员漏写相关代码。

那么token是以怎样的形式传输的呢?我认为有如下两种方式:

Cookie

推荐使用这种方式,由于浏览器每次都会将cookie携带在请求里一并发出,因此前端发送请求的代码都不须要修改,只要在发送请求前问服务器拿token就好了。

好比在进入Form页面时,服务器将token以cookie的形式一并携带在响应中,那么前端Form提交时,就会将cookie一并携带在请求中,前端的代码一点都不须要修改。

json

前端发起ajax请求像后端拿token,后端以json的形式返回token,前端发送请求时将token携带在请求中,后端检验。

这种方式比Cookie稍微麻烦的地方是,前端必须写一些代码来保存这个token,而后在发送请求的地方要写一些代码把token携带在请求里。

优势

  1. 前端代码能够写的少一些,好比禁用UI元素的代码能够不写
  2. 可以解决在还未响应302以前,用户刷新浏览器致使的重复请求
  3. 适应有些场景下压根不能使用重定向

缺点

  1. 前、后端开发人员忘记写相关代码。这个真的解决不了。
  2. 没法控制经过脚本运行的,具备整套流程的恶意请求。这种请求在程序看来彻底合法,但却属于恶意行为,针对这类恶意行为的防控属于另外一个话题,本人不懂,因此在这里就很少讲了。

方法五:利用数据库的惟一约束

若是请求会insert数据,而这个数据正好存在业务主键,那么能够利用数据库的惟一约束来作进一步的防护。

方法六:请求幂等化

有些业务情形下,请求是幂等的,这就意味着能够不用为重复发生请求而烦恼了——至少在业务逻辑层面不用烦恼了。

相关文章
相关标签/搜索