秒杀怎么防机器人:验证码之外的几道防线
秒杀怎么防机器人:验证码之外的几道防线
限量秒杀场景有个普遍现象:活动开始不到一秒就售罄,而正常用户的请求往往一两秒后才到达——抢到的大多是脚本,请求特征高度一致、时间戳精确到毫秒、操作路径和真人完全不同。
「我们有验证码」挡不住这件事:打码平台几毛钱一次,秒级识别。验证码挡得住普通人,挡不住专业团队。
机器人的优势在于速度
正常用户打开页面 → 点按钮 → 请求发出,整个链路至少 1-2 秒。
脚本:活动开始前提前拿好 Token、提前算好请求参数,时间一到立刻发出——比正常用户快 1000 毫秒以上。这 1 秒的优势,在高并发秒杀里决定了一切。
对抗机器人不是要把它们彻底赶走,而是让它们的速度优势消失。
排队队列:请求先进队,不直接打数据库
秒杀请求不要直接更新库存,而是先进队列:
public SeckillResult joinQueue(long userId, long itemId) {
// 1. 用户是否已经在队列中
if (queueService.isInQueue(userId, itemId)) {
return SeckillResult.duplicate();
}
// 2. Redis 原子判断库存
Long remaining = redis.decr("stock:" + itemId);
if (remaining < 0) {
redis.incr("stock:" + itemId); // 回补
return SeckillResult.soldOut();
}
// 3. 进队列,异步创建订单
mqProducer.send(new SeckillMessage(userId, itemId));
return SeckillResult.queuing();
}
库存在 Redis 里预减,减到 0 就拒绝后续请求(不再进队列),保护数据库不被打穿。队列里的消息由 Worker 逐条处理、创建订单,处理速度可控。
请求合法性校验
机器人通常绕过了正常的页面流程,直接构造请求打接口。用页面 Token 校验合法性:
- 用户打开商品详情页时,服务端生成一个
pageToken(UUID,有效期 5 分钟),埋在页面里 - 用户点击"立即购买"时,前端把
pageToken带上 - 后端校验
pageToken:存在且未使用过才允许下单,用过即销毁(一次性)
脚本通常不走打开详情页这一步,拿不到有效的 pageToken,请求被拦截。
对抗手段:攻击者可以爬页面拿 Token。所以还要结合:Token 的颁发频率限制(同一用户 N 秒内只给一个)+ 行为分(没有正常的浏览行为就拿 Token,评分低)。
行为分:操作速度异常
人类的点击操作有自然的时间间隔,鼠标移动有轨迹,机器人没有。
前端采集行为信号:
- 页面停留时长(< 500ms 就点购买:异常)
- 鼠标移动路径(直线、无轨迹:异常)
- 按钮点击位置(每次精确在同一像素:异常)
这些信号打包成行为分上传,行为分过低时要求做人机验证(图形拖拽、算术题)。注意:用行为分触发验证,而不是所有用户都验证——减少正常用户的摩擦。
几道防线叠加
单一手段都可以被绕过,组合防御让攻击成本升高:
| 层次 | 手段 | 机器人成本 |
|---|---|---|
| 请求层 | 接口限流(令牌桶) | 请求频率被压低 |
| 合法性 | pageToken 一次性校验 | 必须完整走页面流程 |
| 行为 | 行为分 + 动态验证码 | 需要逆向前端采集逻辑 |
| 排队 | 队列削峰,速度优势消失 | 快 100ms 进队也没用 |
| 库存 | Redis 预减,DB 不被打穿 | 数据库层有兜底 |
没有银弹,只有成本博弈。防御的目标不是让机器人零成功率,而是让它的攻击成本超过收益,让大多数人放弃。
评论(0)
登录后参与评论。
还没有评论,来抢沙发吧。

