如何防止 HTTP 重复请求

背景

之前就在电信叠加卡系统中发现一个问题,即有部分号码在很短的时间内订购多次同种套餐,并扣除同等金额。本以为是前端在提交后没有 disable 掉提交按钮所导致的客户多次点击重复提交。但今天,即 2017 年 3 月 25 日,再次发现一个号码发生这种情况,在短短 10 秒内,连续提交了 5 次订单。

目标

  • 发现为什么出现这种现象;
  • 如何避免该情况;

问题分析

当前正常访问流程

客户端 -> Cloudflare 反向代理 -> 我自己的服务器 Nginx 反向代理 -> 应用服务器 Express 应用

问题可能存在的节点

每一个箭头代表一次访问,每次访问过程都可能出现多次请求的问题。

相关日志

数据库订购记录:

/* 1 createdAt:2017/3/25 上午11:07:43*/
{
    "_id" : ObjectId("58d5deff6d592135e91b4191"),
    "updatedAt" : ISODate("2017-03-25T11:07:43.260+08:00"),
    "createdAt" : ISODate("2017-03-25T11:07:43.260+08:00"),
    "simcardNo" : "1459207",
    "_packId" : ObjectId("5853b3f6c9e333027664b3c1")
},

/* 2 createdAt:2017/3/25 上午11:07:43*/
{
    "_id" : ObjectId("58d5deff6d592135e91b4192"),
    "updatedAt" : ISODate("2017-03-25T11:07:43.724+08:00"),
    "createdAt" : ISODate("2017-03-25T11:07:43.724+08:00"),
    "simcardNo" : "1459207",
    "_packId" : ObjectId("5853b3f6c9e333027664b3c1")
},

/* 3 createdAt:2017/3/25 上午11:07:44*/
{
    "_id" : ObjectId("58d5df006d592135e91b4193"),
    "updatedAt" : ISODate("2017-03-25T11:07:44.088+08:00"),
    "createdAt" : ISODate("2017-03-25T11:07:44.088+08:00"),
    "simcardNo" : "1459207",
    "_packId" : ObjectId("5853b3f6c9e333027664b3c1")
},

/* 4 createdAt:2017/3/25 上午11:07:44*/
{
    "_id" : ObjectId("58d5df006d592135e91b4194"),
    "updatedAt" : ISODate("2017-03-25T11:07:44.845+08:00"),
    "createdAt" : ISODate("2017-03-25T11:07:44.845+08:00"),
    "simcardNo" : "1459207",
    "_packId" : ObjectId("5853b3f6c9e333027664b3c1")
},

/* 5 createdAt:2017/3/25 上午11:07:55*/
{
    "_id" : ObjectId("58d5df0b6d592135e91b4195"),
    "updatedAt" : ISODate("2017-03-25T11:07:55.153+08:00"),
    "createdAt" : ISODate("2017-03-25T11:07:55.153+08:00"),
    "simcardNo" : "1459207",
    "_packId" : ObjectId("5853b3f6c9e333027664b3c1")
}

我自己的服务器 Nginx 反向代理的日志文件:

172.68.141.158 - - [25/Mar/2017:11:02:18 +0800] "OPTIONS /accounts HTTP/1.1" 204 0 "http://fp.m2m-10000.cn/bind/1459207"
172.68.141.158 - - [25/Mar/2017:11:02:19 +0800] "PATCH /accounts HTTP/1.1" 200 35 "http://fp.m2m-10000.cn/bind/1459207"
172.68.141.158 - - [25/Mar/2017:11:02:19 +0800] "PATCH /accounts HTTP/1.1" 200 35 "http://fp.m2m-10000.cn/bind/1459207"
172.68.141.158 - - [25/Mar/2017:11:02:20 +0800] "PATCH /accounts HTTP/1.1" 200 35 "http://fp.m2m-10000.cn/bind/1459207"
172.68.141.158 - - [25/Mar/2017:11:02:21 +0800] "PATCH /accounts HTTP/1.1" 200 35 "http://fp.m2m-10000.cn/bind/1459207"
172.68.141.158 - - [25/Mar/2017:11:02:31 +0800] "PATCH /accounts HTTP/1.1" 200 35 "http://fp.m2m-10000.cn/bind/1459207"

从该日志可以分析出,第二次访问的时候就产生的多次异常的 http 请求。问题只可能发生在两个地方,要么客户端多次访问 Cloudflare 服务器,要么 Cloudflare 多次访问我的 Nginx 服务器。

后来又做了一个小的项目,最简单的一个留言板的应用,结果发现很多记录都被重复提交了 6、7 次。

你可能感兴趣的:(如何防止 HTTP 重复请求)