最近碰到一个重复提交请求,并能在数据库重复插入多条同样数据的问题。因为需求涉及到的是给用户发放购物卡,直接关系到的是金钱,所以是影响很大的一个问题,比如给一个用户发放100元一次,结果被某些居心不良之人抓到包,直接复制一百个请求,然后在执行就相当于给用户直接发放100元100次了,后果可想而知是非常严重的,所以必须的赶紧解决。
问题还原:在页面点击购物卡审核通过按钮,然后利用抓包工具抓到相应的请求,并复制请求N份,然后继续执行,这时数据库中会保存为每个userid发放了N份购物卡。
问题分析:对于这种问题,第一反应就是在数据库中加入一个唯一索引,这样就算重复请求N次,有唯一索引控制,结果也只会插入一条数据;并且购物卡发放也确实是有个购物卡批次号ID,这个ID针对每次发放来说都是一个唯一ID。但是在存入购物卡发放的record表中时,需求设计的是一个购物卡批次号中的一个userid可以对应多记录,因为购物卡面值最大100,如果一次性发放1000的话那就要一次性插入十条记录。所以加唯一索引的这条道不通。当然也考虑过加入一个字段,然后把这个字段设为唯一索引,但是现在系统已经迭代了多个版本,这里加一个字段,系统其它很多地方也需求跟着修改并需要重新测试,所以加字段也暂不考虑。
既然这两种方式都不通,那就只能针对具体业务流程去进行具体分析了。因为涉及代码安全性,这里贴出主要业务流程的伪代码,这个业务逻辑主要在service层中进行处理的,service层的方法如下:
public void addcardservice(record r){
//新增审批记录,此处操作的是审批表
addcardaudit();
。。。
//发放购物卡,此处操作的购物卡发放表record