登录接口被暴力破解时,限流和锁定并不是同一层级的防护,而是先后触发的两道闸门:先限流,再锁定,限流负责拖延和消耗,锁定负责兜底阻断。这个顺序不是随意的,它决定了攻击者最终能撞开多少口令,也决定了正常用户会不会被误伤。
登录接口被暴力破解时,限流与锁定时序是怎样的?
想象一个攻击脚本正在对着你的登录接口跑字典,第一秒,它用普通频率试探,服务器毫无感觉,第十秒,脚本开始并发请求,此时如果接口没有任何防护,每一次请求都会直接进入密码校验逻辑,真正的时序防护应该是这样的:
- 第1步:请求进入,先检查该IP或账号的访问频率计数。
- 第2步:如果频率超过第一层阈值,比如每分钟10次,接口开始返回慢速响应或要求输入验证码。
- 第3步:攻击者绕过验证码继续高频硬闯,计数累计到第二层阈值,比如每小时失败20次。
- 第4步:账号或IP进入锁定状态,后续请求直接被拒绝,不再进入密码校验流程。
- 第5步:等待锁定时间结束,或通过人工/邮件验证解锁。
锁定时序的前提是限流已经失效或不足以拦截,行业共识认为,限流的意义在于把接口的响应速度降下来,让自动化工具在单位时间内能尝试的密码数量大幅减少;锁定则是当攻击行为已经明显超出人类操作上限时,直接切断入口,两者串联,而不是并列。
从第一次试探到账号被锁,中间经历了什么?
以一次真实的暴力破解过程为例,攻击者拿到一个用户名单,从第一个账号开始跑弱口令,假设你的限流阈值是“同一IP每分钟最多30次登录请求”,当攻击者前30次请求发出后,第31次请求就会收到“操作过于频繁”的提示,这个提示不一定是拒绝,可能是延迟响应,让每次请求多等3秒。
攻击者如果换用代理池,每个IP只发40次请求,IP限流就被绕过了,这时账号锁定就该上场,当某个特定账号在较短时间内连续失败多次,比如5次,系统直接锁定该账号15分钟,这意味着攻击者换100个IP,也无法对这个账号继续尝试。锁定的粒度是账号,限流的粒度是来源,两者配合才能覆盖横向和纵向两种攻击路径。
登录接口限流策略对比:固定窗口、滑动窗口还是令牌桶?
限流策略的选择直接影响暴力破解的最终效果,业内常用的三种方案在应对突发攻击时表现差异很大。
| 策略 | 核心逻辑 | 抗暴力破解能力 | 典型副作用 |
|---|---|---|---|
| 固定窗口 | 每分钟最多N次,窗口结束清零 | 较弱,窗口切换瞬间可突刺 | 窗口尾部请求全部放行,容易压垮后端 |
| 滑动窗口 | 按时间切片滑动计数,精确到秒级 | 中等,能平滑突发流量 | 需要存储更多时间戳,内存开销大 |
| 令牌桶 | 恒定速率生成令牌,桶满则丢弃 | 较强,允许短时突发但总量受限 | 参数调校复杂,误伤概率偏高 |
在登录接口这种场景里,滑动窗口比固定窗口更合适,固定窗口有一个明显缺陷:攻击者在第59秒发起爆发式请求,如果阈值是100次,那么这一秒内100次全部允许,紧接着第60秒窗口重置,又可以再打100次,滑动窗口把时间切成小块,任何一个瞬间的请求量都会被累计,令牌桶虽然能容忍突发,但对登录接口来说,突发请求本身就是危险信号,不建议单独使用。
不同限流策略在暴力破解场景下的表现差异
用具体场景说话,一个正常的用户从公司网络登录,可能同时有50个人共享一个出口IP,如果IP阈值设成每分钟30次,这批人内部就会互相干扰,这时候得把阈值放宽到每分钟200次,但代价是攻击者也能多打170次,这是个典型的权衡问题。
另一种场景是攻击者针对单账号爆破,IP限流完全失效,因为攻击者可以用数千个住宅代理随机来源,此时需要依赖账号维度的限流,单账号每小时最多失败10次”,这个策略跟IP限流无关,所以现实的登录接口限流策略对比,不能只看算法本身,还要看限流维度是IP、账号还是设备指纹,多维度组合是更稳妥的方案。
账号锁定和IP限流有什么区别?
账号锁定和IP限流经常被混为一谈,但在实际运维中,它们的目标对象完全不同。IP限流管的是“谁在请求”,账号锁定管的是“谁被尝试”。
用一张表说明白:
- IP限流:针对请求来源地址,限制单位时间内请求次数,典型配置是Nginx里的
limit_req_zone,或者WAF上的连接速率控制。 - 账号锁定:针对具体的用户名或手机号,限制失败尝试次数,典型配置是Spring Security里的
accountLocked机制,或者自研系统的Redis计数锁。
两者的触发条件不同,IP限流在正常用户偶尔输错密码时不会触发,因为频率低,账号锁定则可能在用户连续输错三次时就被触发,哪怕他来自同一个办公室IP。
分布式暴力破解场景下,IP限流的弱点暴露无遗,攻击者控制一个僵尸网络,每个IP只尝试两次,IP限流完全看不到异常,但账号锁定依然有效,因为无论IP怎么变,被攻击的账号始终不变,每次失败都会在账号的计数上+1,直到锁定,所以防御暴力破解,账号锁定是最终兜底,IP限流只是第一道过滤网。
如何设置登录接口的锁定时间与解锁策略
锁定时间太短,攻击者等几分钟就能继续;锁定时间太长,用户误触后干着急,行业里常见的做法是分级递增锁定,首次连续失败5次,锁定15分钟;再次失败,锁定30分钟;继续失败,锁定2小时,这样的时序设计,既消耗攻击者时间,又给真实用户留出反应余地。
具体操作时,可以在Redis里维护一个键:login:fail:{username},记录连续失败次数,每失败一次,INCR,同时设置过期时间,当计数达到阈值,写入login:locked:{username},然后返回“账号已锁定”的提示,这里需要注意,解锁动作不应该由用户自己通过发送多个验证码来完成,否则攻击者可以伪造解锁请求。 更稳妥的方式是让用户收邮件或短信验证码,验证通过后删除锁定键。
针对接口限流的落地配置建议
如果使用网关或反向代理,直接配置限流规则,例如在Nginx中:
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=10r/m; location /api/login { limit_req zone=login_limit burst=20 nodelay; }
这个配置表示每个IP每分钟最多10次请求,允许20次突发,但注意,这种配置对代理池无效,必须配合应用层的账号锁定逻辑。
在应用代码层面,建议把限流和锁定的状态记录分开,限流数据可以放本地缓存,过期时间短;锁定数据必须放Redis或数据库,因为需要跨实例共享,如果多个应用节点各自存锁定信息,攻击者只要轮询不同节点,就能绕过锁定。
关于登录接口暴力破解限流与锁定的常见问题
为什么登录接口已经限流,还是会被人刷爆?
因为限流的维度覆盖不全,只做了IP限流,没做账号限流,攻击者换IP就能绕过,只做了账号限流,没做IP限流,攻击者可以用大量账号同时对一个IP发起小流量试探,更隐蔽的是,攻击者把请求速率控制在限流阈值以下,比如每分钟5次,持续数小时,限流根本不会触发,这时候要依赖异常行为分析,比如同一账号的登录地点频繁变化,或者请求的时间间隔过于均匀,那极有可能不是真人操作。
锁定用户和锁定IP哪个更安全?
没有绝对安全的单一方案,锁定用户账号的副作用是攻击者可以用批量账号制造“撞库”,导致大量正常用户被锁定,造成拒绝服务,锁定IP的副作用是NAT网络下的多个真实用户共享同一个出口IP,一人触发限流,全公司跟着遭殃,较稳妥的做法是双维度同时算分:单个IP得分过高时降低请求速率,单个账号得分过高时直接锁定,两个维度互相独立又互相参考。
如何设置登录接口的锁定时间才不会被攻破?
锁定时间不宜固定,采用“指数退避”策略,第一次失败锁定5分钟,第二次失败锁定25分钟,第三次失败锁定2小时,第四次失败直接锁定到人工申诉,攻击者的成本会随着时间推移指数上升,而真实用户最多等一轮,设置完成后,务必用两个测试账号演练一遍完整时序:先用错误密码触发阈值,观察响应状态码和Redis中的计数变化,再确认解锁条件能正常工作,验证通过后,这个时序才算真正生效。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/634218.html





