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

294 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.

# 验证码API
<cite>
**本文引用的文件**
- [routes.go](file://internal/handler/routes.go)
- [captcha_handler.go](file://internal/handler/captcha_handler.go)
- [captcha_service.go](file://internal/service/captcha_service.go)
- [redis.go](file://pkg/redis/redis.go)
- [response.go](file://internal/model/response.go)
- [auth_handler.go](file://internal/handler/auth_handler.go)
- [captcha_handler_test.go](file://internal/handler/captcha_handler_test.go)
- [captcha_service_test.go](file://internal/service/captcha_service_test.go)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件面向验证码服务API的使用者与维护者围绕路由组“/api/v1/captcha”下的两个核心端点
- GET /generate生成图形验证码滑块拼图返回主图、滑块图、验证码唯一标识及目标Y坐标等信息。
- POST /verify验证用户提交的滑动偏移量判断是否在容差范围内并在验证通过后清理缓存。
文档将详细说明验证码的生成机制基于滑块拼图算法、有效期管理Redis过期策略、验证流程与状态处理并给出请求/响应示例。同时,说明该服务如何与注册、登录、更换邮箱等功能集成以提升安全性。
## 项目结构
验证码API位于路由组“/api/v1/captcha”由处理器与服务层共同实现底层依赖Redis进行验证码数据的临时存储与过期控制。
```mermaid
graph TB
subgraph "路由层"
R["routes.go<br/>注册 /api/v1/captcha/* 路由"]
end
subgraph "处理器层"
GH["captcha_handler.go<br/>Generate/Verify"]
end
subgraph "服务层"
CS["captcha_service.go<br/>GenerateCaptchaData/VerifyCaptchaData"]
end
subgraph "基础设施"
RC["redis.go<br/>Client 封装"]
end
R --> GH
GH --> CS
CS --> RC
```
图表来源
- [routes.go](file://internal/handler/routes.go#L80-L86)
- [captcha_handler.go](file://internal/handler/captcha_handler.go#L1-L77)
- [captcha_service.go](file://internal/service/captcha_service.go#L1-L166)
- [redis.go](file://pkg/redis/redis.go#L1-L175)
章节来源
- [routes.go](file://internal/handler/routes.go#L80-L86)
## 核心组件
- 路由注册:在路由组“/api/v1/captcha”下注册“/generate”和“/verify”两个端点。
- 处理器:负责参数绑定、调用服务层、组织响应。
- 服务层负责验证码生成滑块拼图、目标坐标提取、Redis存储与过期设置、验证偏移量、容差判断、验证后清理。
- Redis客户端提供Set/Get/Del等基础能力封装错误处理。
章节来源
- [routes.go](file://internal/handler/routes.go#L80-L86)
- [captcha_handler.go](file://internal/handler/captcha_handler.go#L1-L77)
- [captcha_service.go](file://internal/service/captcha_service.go#L1-L166)
- [redis.go](file://pkg/redis/redis.go#L1-L175)
## 架构总览
验证码API采用“路由 -> 处理器 -> 服务 -> Redis”的分层设计。生成阶段将目标坐标与容差信息写入Redis并设置过期时间验证阶段读取目标坐标计算容差并判定有效性通过后立即删除对应键防止重复使用。
```mermaid
sequenceDiagram
participant C as "客户端"
participant G as "Generate 处理器"
participant S as "验证码服务"
participant R as "Redis 客户端"
C->>G : GET /api/v1/captcha/generate
G->>S : GenerateCaptchaData(ctx, redisClient)
S->>S : 生成滑块拼图数据
S->>R : Set(key=captcha : id, value={tx,ty}, expire=5m)
S-->>G : 返回 masterImage, tileImage, captchaId, y
G-->>C : JSON {code,data{masterImage,tileImage,captchaId,y}}
```
图表来源
- [captcha_handler.go](file://internal/handler/captcha_handler.go#L12-L34)
- [captcha_service.go](file://internal/service/captcha_service.go#L76-L135)
- [redis.go](file://pkg/redis/redis.go#L60-L83)
章节来源
- [captcha_handler.go](file://internal/handler/captcha_handler.go#L12-L34)
- [captcha_service.go](file://internal/service/captcha_service.go#L76-L135)
## 详细组件分析
### 路由与端点
- 路由组“/api/v1/captcha”
- GET /generate生成验证码数据主图、滑块图、验证码ID、目标Y坐标
- POST /verify验证用户提交的滑动偏移量。
章节来源
- [routes.go](file://internal/handler/routes.go#L80-L86)
### 生成验证码GET /generate
- 输入:无显式请求体。
- 输出:包含以下字段的数据对象
- masterImage主图base64字符串
- tileImage滑块图base64字符串
- captchaId验证码唯一标识用于后续验证
- y目标Y坐标前端可据此定位滑块初始位置
- 内部流程要点
- 生成唯一ID作为验证码会话标识。
- 生成滑块拼图数据提取目标X/Y坐标。
- 将目标坐标序列化后写入Redis键名前缀为“captcha:”过期时间为300秒5分钟
- 返回主图、滑块图、captchaId与修正后的Y坐标给前端。
请求/响应示例(路径)
- 请求GET /api/v1/captcha/generate
- 响应JSON
- code200
- data.masterImage主图base64
- data.tileImage滑块图base64
- data.captchaId验证码ID
- data.y目标Y坐标
章节来源
- [captcha_handler.go](file://internal/handler/captcha_handler.go#L12-L34)
- [captcha_service.go](file://internal/service/captcha_service.go#L76-L135)
### 验证验证码POST /verify
- 请求体字段
- captchaId必填验证码唯一标识
- dx必填用户滑动的X轴偏移量
- 验证逻辑
- 从Redis读取目标坐标tx, ty
- 使用容差值默认±3像素判断 dx 是否在 [tx-3, tx+3] 范围内。
- 若通过删除Redis中的验证码记录返回成功若失败返回失败。
- 错误处理
- 参数缺失或格式错误返回400。
- Redis查询失败或键不存在返回500或提示“验证码已过期或无效”。
请求/响应示例(路径)
- 请求POST /api/v1/captcha/generate
- JSON{ "captchaId": "...", "dx": 123 }
- 响应:
- 成功JSON { "code": 200, "msg": "验证成功" }
- 失败JSON { "code": 400, "msg": "验证失败,请重试" }
章节来源
- [captcha_handler.go](file://internal/handler/captcha_handler.go#L36-L76)
- [captcha_service.go](file://internal/service/captcha_service.go#L137-L166)
### 验证流程与容差机制
```mermaid
flowchart TD
Start(["开始"]) --> Read["读取Redis中的目标坐标(tx, ty)"]
Read --> Found{"键是否存在?"}
Found --> |否| Expired["返回错误:验证码已过期或无效"]
Found --> |是| Calc["计算 |dx - tx|"]
Calc --> Check{"是否 ≤ 容差(3)"}
Check --> |是| Delete["删除Redis键"]
Delete --> Pass["返回验证成功"]
Check --> |否| Fail["返回验证失败"]
Expired --> End(["结束"])
Pass --> End
Fail --> End
```
图表来源
- [captcha_service.go](file://internal/service/captcha_service.go#L137-L166)
章节来源
- [captcha_service.go](file://internal/service/captcha_service.go#L137-L166)
### 与注册/登录/更换邮箱的安全集成
- 注册(/api/v1/auth/register
- 在注册流程中,前端需先获取图形验证码并完成验证,再提交邮箱验证码(通过 /api/v1/auth/send-code 发送)。
- 后端在注册接口处验证邮箱验证码的有效性,确保注册过程安全。
- 登录(/api/v1/auth/login
- 登录流程通常不强制要求图形验证码但可在高风险场景如异常IP、频繁尝试引入图形验证码作为二次防护。
- 更换邮箱(/api/v1/user/change-email
- 更换邮箱时,建议增加图形验证码与邮箱验证码双重校验,降低账户被恶意修改的风险。
章节来源
- [auth_handler.go](file://internal/handler/auth_handler.go#L17-L84)
- [auth_handler.go](file://internal/handler/auth_handler.go#L149-L192)
## 依赖关系分析
- 路由层依赖处理器层暴露的处理函数。
- 处理器层依赖服务层提供的生成与验证方法。
- 服务层依赖Redis客户端进行数据持久化与过期控制。
- 通用响应模型用于统一返回格式(尽管验证码端点未直接使用该模型,但整体风格一致)。
```mermaid
graph LR
Routes["routes.go"] --> Handler["captcha_handler.go"]
Handler --> Service["captcha_service.go"]
Service --> Redis["redis.go"]
Handler --> Model["response.go"]
```
图表来源
- [routes.go](file://internal/handler/routes.go#L80-L86)
- [captcha_handler.go](file://internal/handler/captcha_handler.go#L1-L77)
- [captcha_service.go](file://internal/service/captcha_service.go#L1-L166)
- [redis.go](file://pkg/redis/redis.go#L1-L175)
- [response.go](file://internal/model/response.go#L1-L86)
章节来源
- [routes.go](file://internal/handler/routes.go#L80-L86)
- [captcha_handler.go](file://internal/handler/captcha_handler.go#L1-L77)
- [captcha_service.go](file://internal/service/captcha_service.go#L1-L166)
- [redis.go](file://pkg/redis/redis.go#L1-L175)
- [response.go](file://internal/model/response.go#L1-L86)
## 性能考虑
- 生成阶段
- 滑块拼图生成与base64编码在单次请求中完成建议在前端缓存主图/滑块图以减少重复生成开销。
- 验证阶段
- Redis读取与删除均为O(1),验证逻辑简单,延迟低。
- 过期策略
- 默认5分钟过期避免长期占用内存过期后自动失效无需手动清理。
- 并发与重复使用
- 验证通过后立即删除Redis键防止同一验证码被重复使用。
章节来源
- [captcha_service.go](file://internal/service/captcha_service.go#L123-L135)
- [captcha_service.go](file://internal/service/captcha_service.go#L157-L166)
## 故障排查指南
- 生成失败
- 现象返回500消息包含“生成验证码失败”。
- 可能原因滑块拼图生成异常、Redis写入失败。
- 排查步骤检查Redis连接状态、确认滑块拼图资源可用。
- 验证失败
- 现象返回500或400消息提示“验证码已过期或无效”或“验证失败请重试”。
- 可能原因captchaId无效或已过期、dx不在容差范围内、Redis读取异常。
- 排查步骤确认captchaId正确、dx传值合理、Redis键存在且未过期。
- 参数错误
- 现象返回400消息提示“参数错误”。
- 可能原因缺少captchaId或dx、JSON格式不正确。
- 排查步骤:检查请求体字段与类型。
章节来源
- [captcha_handler.go](file://internal/handler/captcha_handler.go#L12-L34)
- [captcha_handler.go](file://internal/handler/captcha_handler.go#L36-L76)
- [captcha_service.go](file://internal/service/captcha_service.go#L137-L166)
## 结论
验证码API通过滑块拼图与Redis过期机制提供了轻量级、易部署的人机验证方案。其与注册、登录、更换邮箱等关键流程结合可显著提升账户安全。建议在高风险场景引入图形验证码作为附加防护并优化前端缓存策略以提升用户体验。
## 附录
### 请求/响应示例(路径)
- 获取验证码
- 请求GET /api/v1/captcha/generate
- 响应JSON { "code": 200, "data": { "masterImage": "...", "tileImage": "...", "captchaId": "...", "y": 123 } }
- 验证验证码
- 请求POST /api/v1/captcha/verify
- JSON{ "captchaId": "...", "dx": 123 }
- 响应:
- 成功JSON { "code": 200, "msg": "验证成功" }
- 失败JSON { "code": 400, "msg": "验证失败,请重试" }
章节来源
- [captcha_handler.go](file://internal/handler/captcha_handler.go#L12-L34)
- [captcha_handler.go](file://internal/handler/captcha_handler.go#L36-L76)
### 单元测试要点(路径)
- 验证码生成与过期时间
- 测试TestGenerateCaptchaData_ExpireTime
- 断言过期时间为300秒5分钟
- 验证码验证逻辑
- 测试TestVerifyCaptchaData_Logic
- 断言在容差范围内±3返回成功超出范围返回失败
- Redis键生成
- 测试TestVerifyCaptchaData_RedisKey
- 断言键名为“captcha:{id}”
- 处理器响应格式与错误处理
- 测试TestCaptchaHandler_ResponseFormat、TestCaptchaHandler_ErrorHandling
- 断言:成功/失败响应格式与HTTP状态码
章节来源
- [captcha_service_test.go](file://internal/service/captcha_service_test.go#L1-L175)
- [captcha_handler_test.go](file://internal/handler/captcha_handler_test.go#L1-L134)