如果你曾建造过快件API, 你可能已经达到标准限速中间软件, 在引擎盖下,最简单的限制器使用固定-窗口计数器.
很容易写出:数出收到的请求, 然而,从安全和算法的角度来看,"固定窗口"计数器有一个巨大的盲点.
边界脆弱性(The 2-second Spike) 想象一下,你的端点允许最多每分钟100个请求,在钟上重置每分钟().
这就是攻击者如何绕过限制而不违反你的规则: 中午12点59分,攻击者放出100个请求. (赞成:100/100使用). 12点01分,钟将你的计数器重置到0 12:01:01,攻击者再发出100个请求. (赞成:100/100使用).
对你的服务器代码来说,一切都很好 但实际上,200个请求将你的后端撞入了两秒钟的窗口.
在FinTech或认证系统中,爆裂量足以超过支付网关或成功进行认证-打击.
算法修正:滑动窗口计数器 为了阻止边界突起,我们需要一个不断滑动的窗口,而不是僵硬的时钟重置.
尝试 1: 滑动窗口日志( 高内存) 您为每个用户请求存储一个时间戳数组( a Deque) , 并放下超过60秒的时间戳.
虽然准确,但存储每个请求的时间戳需要$O(N)$的空间.
如果您的 API 收到了上百万个请求, 您的服务器内存会立即死亡 。
尝试2:滑动窗口计数器(Optimal O(1) Math) 与其保留上千倍加分,我们只追踪到两个整数:前一个窗口的请求数和当前窗口的倒数.
当一个请求到达时,我们根据当前窗口所经过的时间计算出一个估计请求的计数: 估计请求=当前计算+(先前的ConstxWindow Size Window Six - Time Elapsed) 如果当前窗口所经过的时间为75%,那么我们只算上个窗口流量的25%.
时间复杂度:取景和算术.
空间复杂:内存足迹(每个IP只有两个反变量).
在 Node.js 中建软件 以下是使用 JavaScript 跟踪状态的轻量级执行: 为什么对于高性能系统 sub-Millisecond 速度 : 决定数学以微秒的分数执行,而不在巨大的数组上延后.
边界平滑度 : 12:59 / 12:01:01 突起的进攻者会立即被阻断 因为12:00:59突起的重量 随即进入计算 生产准备: 在分布式多节点基础设施中,这种精确的数学尺度使用简单和散列键清洁到Redis.
将基本的竞争性编程数据结构和数学应用于API安全,将天真的中相器转化为企业级防御.