如何防止页面重复提交
思路:
重复提交有两方面的含义,
一是操作方面的重复提交,旨在说明一个客户端,一次只能发送一个请求到服务端,如果发出后未收到服务端响应,再次提交,则视为无效提交(重复了)。
二是业务方面,同一个表单,服务端处理了两次,两次都是合法的操作(不违反第一种含义),但是表单可能被处理了两次,如像一个账号转账了两次,金额信息一致,可能后台的交易流水不一致,但是确实产生了两笔交易。
在web项目中,防止重复提交,需要解决以上两种问题,
第一种的解决思路是通过token的思路。
第二种通过业务判断解决
以下部分代码,首先服务端
表单提交前,或者表单加载时,服务端返回客户端token
Session["LAST_TOKEN"] = token;
服务端接收客户端发来的token,同时产生并、注册、返回新的token 以便下次请求使用
string token = Guid.NewGuid().ToString(); if (Session["LAST_TOKEN"] == null || Session["LAST_TOKEN"].ToString() != submitToken) { Session["LAST_TOKEN"] = token; return Json(new { isSuccess = false, message = "提交失败,可能是以下原因导致的:<br/> 1.点击频繁或按键失灵。<br/>2.页面长时间未操作。<br/><font color=\"red\">如已出票,请忽略此消息!未出票,请重试!</font>", code = 510, token }); } Session["LAST_TOKEN"] = token;
以上方式,可解决问题一
下面的方式,解决问题二
Result<string> verfiyResult = this.FilterDuplicateOrderSubmit(bill, VerificationCode); if (!verfiyResult.Success) { return Json(new { isSuccess = false, message = verfiyResult.Message, code = 520, VerificationCode = verfiyResult.Entity, token }); }
服务端检测到重复 ,返回520错误码,同时包含验证码,要求客户端下次请求附加此验证码,才能通过验证
private Result<string> FilterDuplicateOrderSubmit(BillNew bill, string VerificationCode) {if (string.IsNullOrWhiteSpace(bill.Consignee) || string.IsNullOrWhiteSpace(bill.Shipper) || bill.EndDepartId == 0) { return new Result<string>("缺少必要校验信息,不在校验,让业务规则校验", true); } var lastOrderInfo = bill.Consignee + bill.ConsigneePhone + bill.Shipper + bill.ShipperPhone ;if (Session["LAST_ORDER_INFO"] != null && Session["LAST_ORDER_INFO"].ToString() == lastOrderInfo) { var code = RandomString.GetRndStrFor(3, false, false, true); if (Session["LAST_ORDER_INFO_VerificationCode"] == null) { Session["LAST_ORDER_INFO_VerificationCode"] = code; return new Result<string>("<font color=\"red\">本次提交信息与上次提交相似,可能造成重复,请务必核对确认。</font><br/>如确认无误,请在页面右下方输入正确验证码后提交。", false, code); } else { if (Session["LAST_ORDER_INFO_VerificationCode"].ToString() != VerificationCode) { Session["LAST_ORDER_INFO_VerificationCode"] = code; return new Result<string>("输入的验证码不正确,请在页面右下方输入正确验证码后提交。<br/><font color=\"red\">本次提交信息与上次提交相似,可能造成重复,请务必核对确认。</font>", false, code); } else { Session["LAST_ORDER_INFO"] = lastOrderInfo; Session["LAST_ORDER_INFO_VerificationCode"] = null; return new Result<string>("校验通过", true); } } } Session["LAST_ORDER_INFO"] = lastOrderInfo; return new Result<string>("无重复!", true); }