因为安全扫描的问题,它会把线上真实的访问流量进行重放,而且重发时间间隔比较短,导致一个请求变成多次请求,也就是重复提交了。那么怎样解决这个问题呢?

一般来说是通过request token来防止重复提交的。具体实现机制是:

当客户端请求页面时,服务器会通过token标签生成一个随机token,并且将该token放置到全局session当中,然后将该随机数发向客户端;如果客户第一次提交,那么会将该随机数发往服务器端,服务器会接收到该token并且与session中所保存的token进行比较,这时两者的值是相同的,服务器认为是第一次提交,并且将更新服务器端的这个token;如果此时再次重复提交,那么客户端发向服务器端的token还是之前的那个,而服务器端的token则已经发生了变化,两者不同,服务器就认为这是重复提交。

这种方式,一个POST请求是分为两步:

  1. 服务端分配token
  2. 客户端提交请求

比较适合于form表单提交的方式,因为就是两个步骤。但是对于API来说,没有先跳转到表单页面的步骤,那么可以这么处理:

  1. 客户端生成一个token,提交到服务端
  2. 服务端保存一段时间(在这段时间内重复提交相同的token就认为是重复提交)

具体实现方案这么做:

  1. 使用redis来存储request token,并且设置合理的超时时间
  2. 使用注解方便用户控制,使用拦截器尽量对应用透明

TIPS 可以用sign签名的做法防止参数串改。但是不能防止一模一样重复提交。

本文由 arganzheng 创作,采用 CC BY 4.0 许可协议。在保留原文作者、署名以及完整原文链接(https://arganzheng.life/how-to-avoid-form-resubmission.html)的前提下,欢迎各种形式的转载、翻译或商业引用。


COMMENTS

评论存放在 GitHub Discussions, 用 GitHub 账号登录即可发表,支持 Markdown。 想针对正文某句话说?选中那段文字,点浮出的「评论」即可划线评论;觉得哪里写错了,发表时勾上「同时提交 Issue」。 有人回复你时 GitHub 会按你的通知设置发邮件,不用守在这里。

×