From d5d311c2b2fcb7cf33861ac4ac255e1066aa1c2c Mon Sep 17 00:00:00 2001 From: zheng020 Date: Fri, 22 May 2026 13:09:55 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E7=9F=AD=E4=BF=A1=E9=AA=8C=E8=AF=81=E7=A0=81=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 包含三种实现方案(userService集成、独立微服务、gateway)的对比分析, 推荐方案一在userService中直接集成SMS SDK。 Co-Authored-By: Claude Opus 4.7 --- .../specs/2026-05-22-sms-register-design.md | 251 ++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-22-sms-register-design.md diff --git a/docs/superpowers/specs/2026-05-22-sms-register-design.md b/docs/superpowers/specs/2026-05-22-sms-register-design.md new file mode 100644 index 0000000..230f8f5 --- /dev/null +++ b/docs/superpowers/specs/2026-05-22-sms-register-design.md @@ -0,0 +1,251 @@ +# 注册短信验证码功能设计文档 + +- **创建日期**: 2026-05-22 +- **状态**: 待评审 +- **目标**: 在用户注册流程中加入阿里云短信验证码验证 + +--- + +## 1. 背景与需求 + +当前注册流程:`手机号 + 密码 → 设置昵称 → 完成注册` + +需求:在注册前增加短信验证码验证,确保手机号真实有效,防止恶意注册。 + +--- + +## 2. 交互流程设计 + +### 2.1 前端页面变化 + +修改 `frontend/pages/register/register.vue`,在当前页面嵌入短信验证码输入区: + +1. 用户输入手机号后,点击"发送验证码"按钮 +2. 按钮变为倒计时状态(60 秒),期间不可点击 +3. 用户输入收到的验证码 +4. 点击"验证验证码"按钮 +5. 验证通过后解锁密码输入框,继续原有注册流程 + +### 2.2 验证码状态 + +| 状态 | 描述 | +|------|------| +| 未发送 | 默认状态,输入框禁用 | +| 已发送(倒计时中) | 输入框启用,倒计时按钮显示剩余秒数 | +| 已发送(可重发) | 倒计时结束,按钮恢复可点击 | +| 验证成功 | 输入框显示绿色对勾,继续注册流程 | +| 验证失败 | 显示错误提示,用户可重新发送 | + +### 2.3 后端流程 + +``` +用户输入手机号 → 发送验证码请求 → 后端生成6位随机码 → 存入Redis(60秒有效期) → 调用阿里云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 配置原本就在 gateway(OSS 用的是同一套),直接复用 +- 前端请求在网关层就能触发短信,不用穿透到后端服务 +- 网关是单点,处理短信很方便 + +**缺点:** +- 短信发送成功后的后续注册流程还在 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: + +```go +// SMSConfig 短信配置 +SMSConfig struct { + AccessKeyID string + AccessKeySecret string + SignName string // 短信签名 + TemplateCode string // 短信模板CODE + Region string // 区域(默认 cn-hangzhou) +} +``` + +通过环境变量注入: + +```bash +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" +} +``` + +**响应** +```json +{ + "code": 200, + "message": "发送成功", + "data": { + "expires_in": 60 + } +} +``` + +### 8.2 验证验证码 + +**请求** +``` +POST /api/v1/auth/verify-code +Content-Type: application/json + +{ + "mobile": "13800138000", + "code": "123456" +} +``` + +**响应** +```json +{ + "code": 200, + "message": "验证成功", + "data": { + "verified": true + } +} +``` + +--- + +## 9. 错误处理 + +| 场景 | 错误码 | 处理方式 | +|------|--------|----------| +| 手机号格式错误 | 400 | 提示"手机号格式不正确" | +| 短信发送失败 | 500 | 提示"发送失败,请重试" | +| 验证码已过期 | 400 | 提示"验证码已过期,请重新发送" | +| 验证码错误 | 400 | 提示"验证码错误" | +| 验证码已使用 | 400 | 提示"验证码已使用,请重新发送" | +| 发送过于频繁 | 429 | 提示"发送过于频繁,请稍后再试" | + +--- + +## 10. 部署说明 + +1. 在阿里云短信服务控制台创建签名和模板,获取 `SignName` 和 `TemplateCode` +2. 在 `deploy/envs/user.env` 或系统环境变量中配置阿里云 AccessKey +3. 重启 userService 服务 + +--- + +## 11. 待确定事项 + +- [ ] 阿里云短信签名和模板CODE(需在阿里云控制台创建) +- [ ] 验证码有效期(默认 60 秒是否合适) +- [ ] 同一手机号发送频率限制(默认 60 秒内不能重复发送) \ No newline at end of file