Skip to content

登录按邮箱和 IP 计失败、注册按 IP 限频,超了回 429 带 Retry-After - #82

Merged
joesmart merged 5 commits into
mainfrom
joesmart/sec-auth-ratelimit
Oct 23, 2026
Merged

joesmart merged 5 commits into
mainfrom
joesmart/sec-auth-ratelimit

Conversation

@joesmart

@joesmart joesmart commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

改了什么

  • 新增 packages/control-plane/src/http/auth-limits.ts:进程内定窗计数器 AttemptCounter(键做 sha256 摘要、每个计数器最多一万个键、过期的先丢)和取来源 IP 的 clientIp。阈值都是命名常量:同一邮箱 15 分钟失败 5 次、同一 IP 15 分钟失败 200 次、同一 IP 一小时注册 20 次。
  • /api/auth/login:超阈值回 429,带 Retry-After 和「尝试太多次了,请 N 分钟后再试」。锁定期内密码对了也是 429。登录成功清掉该邮箱的计数,退回这一次的 IP 计数。
  • /api/register:按 IP 限频,超了同样回 429。
  • 来源 IP 默认只认 socket 地址。只有显式设了 TRUSTED_PROXY_HOPS=n,才取 X-Forwarded-For 右数第 n 项。.env.example、docs/开发.md、deploy/README.md 都写了;远程 compose 前面有一层 Caddy,默认设成 1。
  • Web 登录页和注册页原样显示服务端的中文文案,代码不用改,补了 Playwright 用例。
  • 附件测试一个文件建二十几个人,改成直接建用户再登录,不走注册。

为什么这么改

  • 先记失败再验密码,验过了再退回。scrypt 要等几百毫秒,这期间并发涌进来的请求也能看到计数,越不过阈值。
  • X-Forwarded-For 客户端能随便填,默认不信它。测试和验收靠每个控制面实例各有一份计数来避开上限,不给本机开 IP 白名单。

怎么验证的

pnpm format:check && pnpm typecheck && pnpm lint      # 通过
pnpm --filter @baize/control-plane test                # Test Files 119 passed | 1 skipped,Tests 1542 passed | 1 skipped
pnpm --filter @baize/e2e test                          # Test Files 26 passed,Tests 53 passed
pnpm --filter @baize/web test                          # vitest 351 passed,Playwright 455 passed

新加的测试:

  • control-plane/test/auth-rate-limit.test.ts(8 条):到阈值回 429 带 Retry-After;锁定期内正确密码也 429;换邮箱不受影响;同 IP 换邮箱到阈值也 429;成功登录清计数;并发;默认不信 XFF;信一层代理时取最右一项;注册限频。
  • control-plane/test/auth-limits.test.ts(3 条):窗口、退回和清零、键数上限。
  • control-plane/test/env.test.ts:TRUSTED_PROXY_HOPS 的解析。
  • web/e2e/01-auth.spec.ts:登录和注册收到 429 时页面显示的提示。

Closes #21

🤖 Generated with Claude Code

https://claude.ai/code/session_01Be3SZps2JjqvyrJ1vbLmni

@joesmart
joesmart force-pushed the joesmart/sec-auth-ratelimit branch from 5d3c953 to 57f89cd Compare October 23, 2026 13:53
@joesmart
joesmart merged commit 392fbf3 into main Oct 23, 2026
1 check passed
@joesmart
joesmart deleted the joesmart/sec-auth-ratelimit branch October 23, 2026 13:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

登录和注册接口没有防暴力尝试

1 participant