发布1-开箱取锁.png

后台登录页是整站唯一一个没有验证码的地方。Typecho 自带的防护只有一个 sleep(3) —— 每次密码错误后停 3 秒,能拖慢脚本,但挡不住"慢慢试",更不会在试错几十次之后把来源关在门外。

所以我写了个插件:同一 IP 在 15 分钟内失败 5 次,锁定 30 分钟;锁定期间即使密码正确,也拒绝登录。

它能做什么

  • 按 IP 统计登录失败次数,达到阈值自动锁定
  • 锁定期间密码正确也拒绝(这点最关键,否则爆破只要撞对一次就前功尽弃)
  • 登录成功后清空该 IP 的失败记录,正常用户完全无感
  • 支持 IP 白名单,避免自己手滑两次就把自己关在门外
  • 三项核心参数都能在后台改,也有现成的默认值
  • 4 KB 单文件,无第三方依赖,无数据库改动,停用即失效

安装

  1. 解压,把 LimitLoginAttempts 整个文件夹上传到 /usr/plugins/
  2. 后台 → 控制台 → 插件 → 找到「登录失败限制」→ 启用
  3. 点「设置」,按需调整参数(不改也能直接用)

不用改主题,不用改伪静态,不用手动建目录。

设置项

设置默认值说明
最大失败次数5同一 IP 在统计窗口内允许的最大失败次数,超过即锁定
统计窗口(分钟)15在这个时间范围内统计失败次数
锁定时长(分钟)30触发上限后禁止登录的时长
IP 白名单空多个 IP 用英文逗号分隔,白名单内的 IP 不受限制

参数都有范围校验:次数 1–100、窗口 1–1440 分钟、锁定 1–10080 分钟(7 天),填超了自动回落到默认值,不会把自己锁死一年。

被锁定之后是什么体验

登录尝试过于频繁,账号已临时锁定,请稍后再试

然后被退回登录页。注意:登录页本身不会提前告诉你"已被锁定",因为 Typecho 的登录流程里没有这个钩子,只有提交之后才判定。这是插件做不到的地方,先说明白。

实现上的几个取舍

写在代码里的几个决定,顺带记录一下思路:

只认 REMOTE_ADDR,不信任 X-Forwarded-For。 后者是请求头,客户端想写什么写什么,信任它等于把锁的钥匙交给攻击者。

数据存在插件目录的 data/attempts.php,文件第一行是 <?php exit; ?>。 这样即使有人直接访问这个文件,PHP 解析到第一行就退出,剩下的 JSON 一个字都不会输出,IP 列表不会泄露。

锁定期内不再累加失败次数。 否则攻击者一直打,锁会被无限延长,等于给了对方一个"永久踢掉站长"的按钮。

自动清理。 超过 24 小时没活动、且不在锁定期的记录会被删掉;总量上限 500 条,防止被大量 IP 撑爆磁盘。

所有统计逻辑都包在 try/catch 里。 记录失败这件事绝对不能影响正常登录,任何一个异常都只吞掉,不往上抛。

几个需要注意的边界

1. 站前有 CDN 时不要用。
套了 Cloudflare 之类的 CDN,REMOTE_ADDR 全是 CDN 的节点 IP,一个人被锁等于全站被锁。这种情况要么别装,要么在 CDN 那层做限流。

2. 动态 IP 会互相误伤。
家用宽带每次拨号换 IP,被锁后换个 IP 就进来了(防不住);反过来,办公网共用出口 IP,一个人输错会牵连同事。建议把自己的常用 IP 填进白名单。

3. 把自己锁在外面了怎么办。
删掉 usr/plugins/LimitLoginAttempts/data/attempts.php 即可,所有锁立即解除,不需要停用插件,也不需要动数据库。

4. 只适用 Typecho 1.3.x。
插件用的是 1.3 的命名空间写法(namespace TypechoPlugin\LimitLoginAttempts),1.2 及更早版本加载不了。

5. 环境要求。
PHP 7.4 以上,在 PHP 8.2 + LiteSpeed 环境实测通过。不需要 Redis、不需要 cron。

它挡不住什么

说清楚比较好,免得装了就觉得高枕无忧:

  • 换 IP 池的分布式爆破 —— 每个 IP 只试一两次,永远达不到阈值。那种要靠按用户名限流或上验证码
  • 已经泄露的密码 —— 这是密码管理的问题,跟限流无关
  • 管理员自己嫌麻烦 —— 如果你经常在手机热点、公司、家里三地切换 IP,被锁的概率不低

一句话:它是门槛,不是保险箱。 但门槛能挡掉绝大多数粗暴脚本,成本几乎为零,值得装。

下载

项目说明
版本1.0.0
大小3.6 KB(zip)
环境Typecho 1.3.x / PHP 7.4+
依赖无

下载地址:https://www.lanzouq.com/ixxxxxxxx  提取码:y139

解压后把 LimitLoginAttempts 文件夹放进 /usr/plugins/,后台启用即可。