chore(git): 更新.gitignore以忽略新的本地文件
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled
This commit is contained in:
330
.qoder/repowiki/zh/content/API参考/认证API/发送验证码.md
Normal file
330
.qoder/repowiki/zh/content/API参考/认证API/发送验证码.md
Normal file
@@ -0,0 +1,330 @@
|
||||
# 发送验证码
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go)
|
||||
- [routes.go](file://internal/handler/routes.go)
|
||||
- [verification_service.go](file://internal/service/verification_service.go)
|
||||
- [common.go](file://internal/types/common.go)
|
||||
- [email.go](file://pkg/email/email.go)
|
||||
- [manager.go](file://pkg/email/manager.go)
|
||||
- [redis.go](file://pkg/redis/redis.go)
|
||||
- [manager.go](file://pkg/redis/manager.go)
|
||||
- [config.go](file://pkg/config/config.go)
|
||||
- [main.go](file://cmd/server/main.go)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件面向“发送验证码”API,围绕 /api/v1/auth/send-code 端点进行完整说明。内容包括:
|
||||
- 接口概述与HTTP规范
|
||||
- 请求体结构与字段约束(email、type)
|
||||
- 响应格式与错误码
|
||||
- 验证码生成、存储与过期策略(Redis)
|
||||
- 邮件服务集成(pkg/email)
|
||||
- 不同验证码类型(注册、重置密码、更换邮箱)的处理逻辑
|
||||
- 实际请求与响应示例
|
||||
- 安全注意事项(频率限制、邮箱格式)
|
||||
|
||||
## 项目结构
|
||||
/api/v1/auth/send-code 属于认证模块,位于 Gin 路由分组 /api/v1/auth 下,由处理器负责接收请求、绑定参数、调用服务层发送验证码,并通过 Redis 与邮件服务完成验证码的持久化与发送。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
Client["客户端"] --> Router["Gin 路由<br/>/api/v1/auth/send-code"]
|
||||
Router --> Handler["处理器<br/>SendVerificationCode"]
|
||||
Handler --> Service["服务层<br/>SendVerificationCode/VerifyCode"]
|
||||
Service --> Redis["Redis 客户端<br/>存储验证码/频率限制"]
|
||||
Service --> Email["邮件服务<br/>发送验证码邮件"]
|
||||
Email --> SMTP["SMTP 服务器"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [routes.go](file://internal/handler/routes.go#L16-L26)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L149-L192)
|
||||
- [verification_service.go](file://internal/service/verification_service.go#L40-L118)
|
||||
- [redis.go](file://pkg/redis/redis.go#L60-L83)
|
||||
- [email.go](file://pkg/email/email.go#L29-L105)
|
||||
|
||||
章节来源
|
||||
- [routes.go](file://internal/handler/routes.go#L16-L26)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L149-L192)
|
||||
|
||||
## 核心组件
|
||||
- 路由与处理器
|
||||
- 路由注册:/api/v1/auth/send-code 绑定到 SendVerificationCode 处理器。
|
||||
- 处理器职责:参数绑定、调用服务层发送验证码、记录日志、返回统一响应。
|
||||
- 服务层
|
||||
- 生成6位数字验证码;按 type 与 email 组合键存储至 Redis,设置过期时间;设置发送频率限制;调用邮件服务发送对应类型的邮件。
|
||||
- Redis
|
||||
- 提供 Set/Get/Del/Exists 等基础操作,封装过期时间控制与错误处理。
|
||||
- 邮件服务
|
||||
- 基于 SMTP 的邮件发送,支持 465(隐式 TLS)与 587(显式 TLS)端口;根据 type 选择不同主题与正文模板。
|
||||
- 类型定义
|
||||
- SendVerificationCodeRequest 包含 email 与 type 字段,type 限定为 register/reset_password/change_email。
|
||||
|
||||
章节来源
|
||||
- [routes.go](file://internal/handler/routes.go#L16-L26)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L149-L192)
|
||||
- [verification_service.go](file://internal/service/verification_service.go#L14-L24)
|
||||
- [redis.go](file://pkg/redis/redis.go#L60-L83)
|
||||
- [email.go](file://pkg/email/email.go#L29-L105)
|
||||
- [common.go](file://internal/types/common.go#L49-L54)
|
||||
|
||||
## 架构总览
|
||||
发送验证码的端到端流程如下:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as "客户端"
|
||||
participant H as "处理器<br/>SendVerificationCode"
|
||||
participant S as "服务层<br/>SendVerificationCode/VerifyCode"
|
||||
participant R as "Redis 客户端"
|
||||
participant E as "邮件服务<br/>SendVerificationCode"
|
||||
participant M as "SMTP 服务器"
|
||||
C->>H : POST /api/v1/auth/send-code<br/>{email, type}
|
||||
H->>H : 绑定请求体并校验
|
||||
H->>S : SendVerificationCode(ctx, redis, email, type)
|
||||
S->>R : Exists(rate_limit_key)
|
||||
alt 已存在
|
||||
S-->>H : 返回“发送过于频繁”
|
||||
H-->>C : 400 错误
|
||||
else 不存在
|
||||
S->>S : 生成6位数字验证码
|
||||
S->>R : Set(code_key, code, 10分钟)
|
||||
S->>R : Set(rate_limit_key, 1, 1分钟)
|
||||
S->>E : 根据type发送邮件
|
||||
E->>M : 发送邮件
|
||||
M-->>E : 成功/失败
|
||||
alt 邮件发送失败
|
||||
S->>R : Del(code_key)
|
||||
S-->>H : 返回“发送邮件失败”
|
||||
H-->>C : 400 错误
|
||||
else 成功
|
||||
S-->>H : 返回成功
|
||||
H-->>C : 200 成功
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L149-L192)
|
||||
- [verification_service.go](file://internal/service/verification_service.go#L40-L118)
|
||||
- [redis.go](file://pkg/redis/redis.go#L60-L83)
|
||||
- [email.go](file://pkg/email/email.go#L29-L105)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### HTTP 端点定义
|
||||
- 方法:POST
|
||||
- 路径:/api/v1/auth/send-code
|
||||
- 功能:根据邮箱与类型发送验证码邮件,并在 Redis 中存储验证码及频率限制。
|
||||
|
||||
章节来源
|
||||
- [routes.go](file://internal/handler/routes.go#L16-L26)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L149-L192)
|
||||
|
||||
### 请求体结构
|
||||
- 字段
|
||||
- email: 必填,需符合邮箱格式
|
||||
- type: 必填,枚举值为 register/reset_password/change_email
|
||||
- 参数绑定与校验
|
||||
- 使用 Gin 的绑定与验证机制,确保 email 符合邮箱格式,type 在允许范围内。
|
||||
|
||||
章节来源
|
||||
- [common.go](file://internal/types/common.go#L49-L54)
|
||||
|
||||
### 响应格式
|
||||
- 成功
|
||||
- 状态码:200
|
||||
- 结构:统一响应体,包含 message 字段提示“验证码已发送,请查收邮件”
|
||||
- 失败
|
||||
- 状态码:400
|
||||
- 结构:统一错误响应体,包含错误码与错误信息
|
||||
|
||||
章节来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L149-L192)
|
||||
|
||||
### 错误码与错误场景
|
||||
- 400 参数错误
|
||||
- 请求体绑定失败或参数校验失败
|
||||
- 400 发送过于频繁
|
||||
- Redis 中存在频率限制键(1分钟内)
|
||||
- 400 邮件发送失败
|
||||
- 邮件服务未启用或 SMTP 发送异常
|
||||
- 400 验证码已过期或不存在
|
||||
- 验证码校验时 Redis 中无对应键
|
||||
|
||||
章节来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L149-L192)
|
||||
- [verification_service.go](file://internal/service/verification_service.go#L40-L118)
|
||||
|
||||
### 验证码生成与存储(Redis)
|
||||
- 生成规则
|
||||
- 6位数字验证码
|
||||
- 存储键
|
||||
- 验证码键:verification:code:{type}:{email}
|
||||
- 过期时间:10分钟
|
||||
- 频率限制
|
||||
- 频率限制键:verification:rate_limit:{type}:{email}
|
||||
- 过期时间:1分钟
|
||||
- Redis 操作
|
||||
- Set/SetEx:写入验证码与频率限制
|
||||
- Get:读取验证码用于校验
|
||||
- Del:验证成功后删除验证码键
|
||||
- Exists:检查是否处于发送冷却
|
||||
|
||||
章节来源
|
||||
- [verification_service.go](file://internal/service/verification_service.go#L14-L24)
|
||||
- [verification_service.go](file://internal/service/verification_service.go#L40-L118)
|
||||
- [redis.go](file://pkg/redis/redis.go#L60-L83)
|
||||
|
||||
### 邮件服务集成(pkg/email)
|
||||
- 初始化
|
||||
- 通过全局初始化函数完成一次性初始化,随后通过 MustGetService 获取实例
|
||||
- 发送逻辑
|
||||
- 根据 type 选择不同主题与正文模板
|
||||
- 支持 465(隐式 TLS)与 587(显式 TLS)两种端口模式
|
||||
- 当邮件服务未启用时,返回“邮件服务未启用”的错误
|
||||
- 主题与正文
|
||||
- 注册:邮箱验证
|
||||
- 重置密码:重置密码
|
||||
- 更换邮箱:更换邮箱验证
|
||||
- 默认:通用验证码
|
||||
|
||||
章节来源
|
||||
- [email.go](file://pkg/email/email.go#L29-L105)
|
||||
- [manager.go](file://pkg/email/manager.go#L1-L43)
|
||||
- [main.go](file://cmd/server/main.go#L71-L74)
|
||||
|
||||
### 不同验证码类型的处理逻辑
|
||||
- 注册(register)
|
||||
- 邮件主题:邮箱验证
|
||||
- 通常配合注册接口使用,注册时需提供验证码
|
||||
- 重置密码(reset_password)
|
||||
- 邮件主题:重置密码
|
||||
- 与 /api/v1/auth/reset-password 配合使用
|
||||
- 更换邮箱(change_email)
|
||||
- 邮件主题:更换邮箱验证
|
||||
- 与用户更换邮箱流程配合使用
|
||||
- 默认(其他)
|
||||
- 通用验证码主题
|
||||
|
||||
章节来源
|
||||
- [verification_service.go](file://internal/service/verification_service.go#L106-L118)
|
||||
- [email.go](file://pkg/email/email.go#L107-L139)
|
||||
|
||||
### 安全考虑
|
||||
- 邮箱格式验证
|
||||
- 请求体中 email 字段使用邮箱格式校验
|
||||
- 发送频率限制
|
||||
- Redis 中按 type+email 维度设置1分钟冷却,避免刷屏
|
||||
- 验证码有效期
|
||||
- Redis 中验证码设置10分钟过期,过期即失效
|
||||
- 重复使用防护
|
||||
- 验证码校验成功后立即删除键,防止二次使用
|
||||
- 邮件服务开关
|
||||
- 若未启用邮件服务,发送验证码会直接失败,避免泄露敏感信息
|
||||
|
||||
章节来源
|
||||
- [common.go](file://internal/types/common.go#L49-L54)
|
||||
- [verification_service.go](file://internal/service/verification_service.go#L40-L118)
|
||||
- [redis.go](file://pkg/redis/redis.go#L60-L83)
|
||||
- [email.go](file://pkg/email/email.go#L29-L40)
|
||||
|
||||
## 依赖关系分析
|
||||
- 处理器依赖服务层
|
||||
- 服务层依赖 Redis 与邮件服务
|
||||
- 邮件服务依赖配置与日志
|
||||
- Redis 客户端依赖配置与日志
|
||||
- 全局初始化顺序:配置 -> 日志 -> 数据库 -> JWT -> Redis -> 对象存储 -> 邮件服务
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
H["处理器<br/>auth_handler.go"] --> S["服务层<br/>verification_service.go"]
|
||||
S --> R["Redis 客户端<br/>redis.go"]
|
||||
S --> E["邮件服务<br/>email.go"]
|
||||
E --> Cfg["配置<br/>config.go"]
|
||||
E --> Lg["日志"]
|
||||
R --> Cfg
|
||||
R --> Lg
|
||||
Main["服务启动<br/>main.go"] --> E
|
||||
Main --> R
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L149-L192)
|
||||
- [verification_service.go](file://internal/service/verification_service.go#L40-L118)
|
||||
- [redis.go](file://pkg/redis/redis.go#L60-L83)
|
||||
- [email.go](file://pkg/email/email.go#L29-L105)
|
||||
- [config.go](file://pkg/config/config.go#L49-L107)
|
||||
- [main.go](file://cmd/server/main.go#L27-L74)
|
||||
|
||||
章节来源
|
||||
- [main.go](file://cmd/server/main.go#L27-L74)
|
||||
|
||||
## 性能考量
|
||||
- Redis 操作均为 O(1),Set/Get/Del/Exists 均为常数时间复杂度
|
||||
- 验证码长度固定为6位,生成与比较成本低
|
||||
- 邮件发送为外部依赖,受网络与SMTP服务器性能影响
|
||||
- 建议
|
||||
- 合理设置 Redis 连接池大小(PoolSize)
|
||||
- 控制邮件发送并发,避免瞬时高峰导致SMTP限流
|
||||
- 对高频请求开启更严格的频率限制(如增加冷却时间)
|
||||
|
||||
[本节为通用性能建议,不直接分析具体文件]
|
||||
|
||||
## 故障排查指南
|
||||
- 400 参数错误
|
||||
- 检查请求体是否包含 email 与 type,且 type 是否在允许范围内
|
||||
- 400 发送过于频繁
|
||||
- 等待1分钟冷却时间,或检查 Redis 中 rate_limit 键是否仍存在
|
||||
- 400 邮件发送失败
|
||||
- 确认邮件服务已启用(EMAIL_ENABLED=true)
|
||||
- 检查 SMTP 配置(主机、端口、用户名、密码、发件人名称)
|
||||
- 查看日志中 SMTP 发送错误信息
|
||||
- 400 验证码已过期或不存在
|
||||
- 检查 Redis 中 code 键是否存在与过期时间
|
||||
- 确认验证码是否已被验证成功后删除
|
||||
|
||||
章节来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L149-L192)
|
||||
- [verification_service.go](file://internal/service/verification_service.go#L40-L118)
|
||||
- [email.go](file://pkg/email/email.go#L29-L105)
|
||||
- [redis.go](file://pkg/redis/redis.go#L60-L83)
|
||||
|
||||
## 结论
|
||||
/api/v1/auth/send-code 端点通过 Gin 处理器接收请求,调用服务层完成验证码生成、Redis 存储与频率限制、邮件发送等流程。其设计遵循最小暴露面原则:严格参数校验、冷却时间、过期时间与删除机制共同保障安全性与可用性。结合 pkg/email 与 pkg/redis 的稳定实现,整体具备良好的扩展性与可维护性。
|
||||
|
||||
[本节为总结性内容,不直接分析具体文件]
|
||||
|
||||
## 附录
|
||||
|
||||
### 请求与响应示例
|
||||
- 请求示例
|
||||
- 方法:POST
|
||||
- 路径:/api/v1/auth/send-code
|
||||
- 请求体:
|
||||
- email: user@example.com
|
||||
- type: register 或 reset_password 或 change_email
|
||||
- 成功响应示例
|
||||
- 状态码:200
|
||||
- 响应体:包含 message 字段,提示“验证码已发送,请查收邮件”
|
||||
- 失败响应示例
|
||||
- 状态码:400
|
||||
- 响应体:包含错误码与错误信息,如“发送过于频繁,请稍后再试”或“发送邮件失败”
|
||||
|
||||
章节来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L149-L192)
|
||||
- [common.go](file://internal/types/common.go#L49-L54)
|
||||
Reference in New Issue
Block a user