Files
backend/.qoder/repowiki/zh/content/API参考/认证API/发送验证码.md
lan a4b6c5011e
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled
chore(git): 更新.gitignore以忽略新的本地文件
2025-11-30 08:33:17 +08:00

330 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 发送验证码
<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)