web开发之表单重复提交

一、什么是表单重复提交

当我们在淘宝购物的时候,在付款的最后一步,也就是在表单输入密码提交后,系统完成扣钱并返回支付成功信息给前台。
当然我们看到的时候,页面跳转到了支付成功页面,而不是在当前页面做的响应。这其实是因为淘宝已经做了防止重复提交的应对机制。
但是最初大家开发网页的时候,都用的是最简单的请求-响应方式。浏览器的地址是不变的,表单数据也存在缓存之中。此时如果做一些表单重复提交的操作,如果后台不验证订单是否已经付款的话,我们可能就会重复付钱给淘宝了。这当然是一个BUG。

有几种方式呢?
1.重复点击了提交按钮(可能是由于网络延迟,我们还没收到响应的时候又着急点击了提交)
2.提交成功后,点击了浏览器的refresh按钮
3.浏览器前进或后退方式,重复执行了uri
4.其他种种导致上一次http重新被请求了

二、解决方案

1.首先我们会想到在js端控制
当用户点击提交按钮过后,通过javascript脚本控制按钮在收到响应之前不可再被点击。
这是前端控制方案,对一个有良好用户体验的网站,这个控制是必须要做到的。
缺点是:网页刷新或者前进、后退导致的刷新一样会重复提交表单。

2.表单提交成功后,后台不直接返回响应,而是通过重定向的方式,让客户端重新请求成功的页面
这种方式被称为Post/Redirect/Get方式,简称为PRG。 PRG是一种web开发设计模式。该模式的主要作用就是为了防止表单重复提交问题。该种方式解决了网页刷新和前进、后退导致的重复提交问题。
缺点是:由于服务器延迟,导致的用户多次提交问题还是不能避免。

对于一般用户而言,结合上两种情况,基本可以保证避免重复提交问题。首先任何情况下用javascript控制提交按钮只能响应一次,其次是提交成功后,使用重定向方式,使前端重新请求其他成功页面。
如果某个用户,在提交后,由于网络问题,发现等待很久,而提交按钮此时不可用,然后他选择了点击浏览器刷新按钮(一般用户不会这样干的)想试试能不能改变这种网络状况的时候,重复提交的问题就又出现了。(不过这个说法有待商榷,经测试,当后台一直处于响应中的状态时,chrome浏览器的refresh按钮是变成X的,显示的是停止加载此页,那么此时停止后,页面并没有提交到后台呢,还是在原来的页面)

3.100%解决重复提交问题
需要服务端和客户端联合编程完全解决重复提交问题。即采用token机制。
在服务器端session保存唯一token,并在生成表单页面时,将该token以隐藏表单域的方式记录在前端,当表单提交时候,用服务端session和提交的token比对,如果一致,则是第一次提交,清空服务器端session的token。
则如果重复提交的话,服务器端session和提交的token是不一致的。如此,便可判断表单是否重复提交。


参考资料:
Post/Redirect/Get
服务器端防止表单重复提交

posted @ 2016-08-25 23:29  braveliu.site  阅读(321)  评论(0编辑  收藏  举报