topfans/docs/superpowers/specs/2026-05-22-sms-register-design.md
zheng020 d5d311c2b2 docs: 添加注册短信验证码功能设计文档
包含三种实现方案(userService集成、独立微服务、gateway)的对比分析,
推荐方案一在userService中直接集成SMS SDK。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:43:43 +08:00

6.7 KiB
Raw Blame History

注册短信验证码功能设计文档

  • 创建日期: 2026-05-22
  • 状态: 待评审
  • 目标: 在用户注册流程中加入阿里云短信验证码验证

1. 背景与需求

当前注册流程:手机号 + 密码 → 设置昵称 → 完成注册

需求:在注册前增加短信验证码验证,确保手机号真实有效,防止恶意注册。


2. 交互流程设计

2.1 前端页面变化

修改 frontend/pages/register/register.vue,在当前页面嵌入短信验证码输入区:

  1. 用户输入手机号后,点击"发送验证码"按钮
  2. 按钮变为倒计时状态60 秒),期间不可点击
  3. 用户输入收到的验证码
  4. 点击"验证验证码"按钮
  5. 验证通过后解锁密码输入框,继续原有注册流程

2.2 验证码状态

状态 描述
未发送 默认状态,输入框禁用
已发送(倒计时中) 输入框启用,倒计时按钮显示剩余秒数
已发送(可重发) 倒计时结束,按钮恢复可点击
验证成功 输入框显示绿色对勾,继续注册流程
验证失败 显示错误提示,用户可重新发送

2.3 后端流程

用户输入手机号 → 发送验证码请求 → 后端生成6位随机码 → 存入Redis60秒有效期 → 调用阿里云SMS API → 返回前端
用户输入验证码 → 验证请求 → 后端从Redis取出比对 → 一致则标记验证成功 → 继续注册流程

3. 实现方案

方案一:在 userService 中直接集成 SMS SDK推荐

前端 → 网关 /auth/send-code → userService → 阿里云SMS
前端 → 网关 /auth/verify-code → userService → Redis验证 → 继续注册流程

优点:

  • 注册逻辑集中在一个服务,流程一目了然
  • userService 已有完整注册流程,加 SMS 只是顺带的事
  • Redis 已在 userService 中可用,不用跨服务调用
  • 部署简单,只增加一个 SDK 依赖

缺点:

  • userService 多了一个外部依赖(阿里云 SMS SDK升级 SDK 时需重新编译
  • 如果未来短信需求变复杂userService 会越来越臃肿

适用场景:当前阶段最合适,注册流程本来就在 userService不需要为了"未来的扩展性"增加复杂度。


方案二SMS 单独作为一个微服务

前端 → 网关 /auth/send-code → 短信Service → 阿里云SMS
前端 → 网关 /auth/verify-code → userService → Redis验证

优点:

  • 职责单一,短信服务可以独立迭代
  • 未来如果加邮件、推送通知,继续扩展这个服务即可
  • userService 保持干净,不感知第三方服务细节

缺点:

  • 需要额外部署一个服务,增加运维复杂度
  • 注册流程跨两个服务,一次注册调用两次 Dubbo延迟增加
  • 目前项目没有独立的通知服务,新增一个微服务成本偏高

适用场景:适合未来有多渠道通知需求的大规模系统。


方案三:在 gateway 层调用 SMS

前端 → 网关 /auth/send-code → 阿里云SMS网关直接调用
前端 → 网关 /auth/verify-code → userService → Redis验证

优点:

  • 阿里云 credentials 配置原本就在 gatewayOSS 用的是同一套),直接复用
  • 前端请求在网关层就能触发短信,不用穿透到后端服务
  • 网关是单点,处理短信很方便

缺点:

  • 短信发送成功后的后续注册流程还在 userService逻辑割裂
  • 网关承担了越来越多的职责路由、认证、OSS上传、现在又加短信越来越重
  • 如果 SMS 认证配置要从 gateway 复用,需要确保 userService 能访问到同一份配置,增加了部署耦合

适用场景:适合短信作为独立操作、不属于用户注册主流程的场景。


4. 方案对比

方案一userService 方案二(独立微服务) 方案三gateway
部署复杂度
延迟
逻辑内聚性 (注册+短信在一起) 高(短信独立) 差(分散在两处)
可扩展性
维护成本

5. 技术选型

项目 选择
短信 SDK github.com/aliyundysms/dysmsapi-go-sdk(阿里官方 Go SDK
认证方式 AccessKeyID/Secret与 OSS 配置复用同一套)
验证码存储 Redis已部署过期自动失效
推荐方案 方案一userService

6. 配置项

backend/gateway/config/config.go 的 OSSConfig 基础上新增 SMSConfig

// SMSConfig 短信配置
SMSConfig struct {
    AccessKeyID     string
    AccessKeySecret string
    SignName        string        // 短信签名
    TemplateCode    string        // 短信模板CODE
    Region          string        // 区域(默认 cn-hangzhou
}

通过环境变量注入:

SMS_ACCESS_KEY_ID=
SMS_ACCESS_KEY_SECRET=
SMS_SIGN_NAME=TopFans
SMS_TEMPLATE_CODE=SMS_xxxxxxx
SMS_REGION=cn-hangzhou

7. Redis 存储设计

Key 格式: sms:verify:{mobile}

Value: 6位验证码字符串

TTL: 60 秒

验证后: 删除 Key 或标记已使用(防止重放)


8. API 设计

8.1 发送验证码

请求

POST /api/v1/auth/send-code
Content-Type: application/json

{
    "mobile": "13800138000"
}

响应

{
    "code": 200,
    "message": "发送成功",
    "data": {
        "expires_in": 60
    }
}

8.2 验证验证码

请求

POST /api/v1/auth/verify-code
Content-Type: application/json

{
    "mobile": "13800138000",
    "code": "123456"
}

响应

{
    "code": 200,
    "message": "验证成功",
    "data": {
        "verified": true
    }
}

9. 错误处理

场景 错误码 处理方式
手机号格式错误 400 提示"手机号格式不正确"
短信发送失败 500 提示"发送失败,请重试"
验证码已过期 400 提示"验证码已过期,请重新发送"
验证码错误 400 提示"验证码错误"
验证码已使用 400 提示"验证码已使用,请重新发送"
发送过于频繁 429 提示"发送过于频繁,请稍后再试"

10. 部署说明

  1. 在阿里云短信服务控制台创建签名和模板,获取 SignNameTemplateCode
  2. deploy/envs/user.env 或系统环境变量中配置阿里云 AccessKey
  3. 重启 userService 服务

11. 待确定事项

  • 阿里云短信签名和模板CODE需在阿里云控制台创建
  • 验证码有效期(默认 60 秒是否合适)
  • 同一手机号发送频率限制(默认 60 秒内不能重复发送)