Skip to content

feat(auth): OTP 注册引擎(待注册态 + 验证码,review 后重做) - #52

Merged
longsizhuo merged 2 commits into
mainfrom
feat/otp-registration
Jul 24, 2026
Merged

longsizhuo merged 2 commits into
mainfrom
feat/otp-registration

Conversation

@longsizhuo

Copy link
Copy Markdown
Member

ADR-001 规范邮箱子系统的引擎。原 #51 因基分支 feat/resend-email(=#50,已 squash 合入 main)被删而被 GitHub 自动关闭,本 PR 顶替它,已 rebase 到 main。

范围(只做引擎,不改认证主流程)

  • PendingRegistration:待邮箱验证的注册意图,进程内 Caffeine,不落库。
  • RegistrationService:begin → pendingId;sendOtp(pendingId,email) → 6 位码 + Resend 发信;verifyAndConsume(pendingId,email,code) → 成功返回已验证邮箱 + 一次性消费。

xhigh review 后重做的安全模型

  • 爆破封堵:verifyAttempts 累积在会话上、不被重发重置 → 6 位码爆破面恒为 5/1e6。
  • 邮件轰炸:发信限流(会话至多 5 封、间隔 ≥60s)+ 邮箱格式校验。
  • 原子一次性:校验+消费在会话锁内完成,并发/双击只成功一次,杜绝重复建号。
  • 邮箱验证不被架空:返回本次实际验证通过的 email(VerifiedRegistration),不再返回 provider 预填的未验证地址。
  • TTL 不错配:单缓存可变会话,pending 与 OTP 同生命周期,会话 15min 不被重发刷新。
  • 单实例内存态 / pendingId DoS 兜底在类注释里写明(多实例迁 Redis)。

验证

11 引擎测试(一次性 / 累积限次 / 重发不重置 attempts / 重发上限 / 冷却 / OTP 过期 / 邮箱绑定 / 返回已验证邮箱 / 并发只消费一次);全量 283 通过。

下一步(wiring PR)

loginByProvider → AuthOutcome(LoggedIn | NeedsEmailVerification);OAuthController 新用户分支跳验证页;RegistrationController 的 send-otp/verify-otp 端点;verify 通过后建号/关联 + 登入。之后前端两步页 —— 这一步会重新启用 Discord 按钮。

🤖 Generated with Claude Code

https://claude.ai/code/session_01RtSNVtrEkCsFVHrbt4Zjgi

ADR-001 规范邮箱子系统的引擎部分(自包含可测):
- PendingRegistration:待邮箱验证的注册意图,进程内 Caffeine(15min TTL,不落库)
- RegistrationService.begin/sendOtp/verifyAndConsume:6 位码,10min TTL,
  限 5 次防爆破,邮箱与发码对象绑定(防换邮箱绕过),一次性消费
- 发信复用 ResendEmailService;发信失败返 false 供调用方作可重试用户错误

账号建号/关联的落地留给 wiring PR(改认证主流程,单独隔离)。
6 引擎测试;全量 278 通过。
review 发现的漏洞集中修:
- 【爆破封堵】attempts 累积在会话上、不被重发重置 → 6 位码爆破面恒为 5 次
- 【邮件轰炸】发信限流:会话至多 5 封、间隔 ≥60s;邮箱格式校验
- 【原子一次性】校验+消费在会话锁内完成,并发/双击只成功一次,不再重复建号
- 【邮箱验证不被架空】返回本次实际验证通过的 email(VerifiedRegistration),
  不再返回 provider 预填的未验证地址
- 【TTL 错配】单缓存可变会话,pending 与 OTP 同生命周期,会话 15min 不被重发刷新
- OTP 过期显式判定;String.format 指定 Locale.ROOT;SendResult 区分失败语义
- 可注入 Ticker,新增测试:重发不重置 attempts / 重发上限 / 冷却 / OTP 过期 /
  并发只消费一次 / 返回已验证邮箱

单实例内存态限制(多实例/native 需迁 Redis)与 pendingId 耗尽型 DoS(靠随机
UUID+短命+控制层 IP 限流)在类注释里写明。全量 283 测试通过。
Copilot AI review requested due to automatic review settings July 24, 2026 14:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@longsizhuo
longsizhuo merged commit 05cc00c into main Jul 24, 2026
@longsizhuo
longsizhuo deleted the feat/otp-registration branch July 24, 2026 14:27
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.

2 participants