352 lines
13 KiB
Markdown
352 lines
13 KiB
Markdown
|
|
# 用户注册
|
|||
|
|
|
|||
|
|
<cite>
|
|||
|
|
**本文引用的文件**
|
|||
|
|
- [auth_handler.go](file://internal/handler/auth_handler.go)
|
|||
|
|
- [routes.go](file://internal/handler/routes.go)
|
|||
|
|
- [common.go](file://internal/types/common.go)
|
|||
|
|
- [response.go](file://internal/model/response.go)
|
|||
|
|
- [user_service.go](file://internal/service/user_service.go)
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go)
|
|||
|
|
- [password.go](file://pkg/auth/password.go)
|
|||
|
|
- [user.go](file://internal/model/user.go)
|
|||
|
|
- [auth_handler_test.go](file://internal/handler/auth_handler_test.go)
|
|||
|
|
- [common_test.go](file://internal/types/common_test.go)
|
|||
|
|
</cite>
|
|||
|
|
|
|||
|
|
## 目录
|
|||
|
|
1. [简介](#简介)
|
|||
|
|
2. [项目结构](#项目结构)
|
|||
|
|
3. [核心组件](#核心组件)
|
|||
|
|
4. [架构总览](#架构总览)
|
|||
|
|
5. [详细组件分析](#详细组件分析)
|
|||
|
|
6. [依赖关系分析](#依赖关系分析)
|
|||
|
|
7. [性能与扩展性](#性能与扩展性)
|
|||
|
|
8. [故障排查指南](#故障排查指南)
|
|||
|
|
9. [结论](#结论)
|
|||
|
|
10. [附录](#附录)
|
|||
|
|
|
|||
|
|
## 简介
|
|||
|
|
本文件面向“用户注册”API,围绕 /api/v1/auth/register 端点进行完整说明。内容覆盖:
|
|||
|
|
- HTTP 方法与路由
|
|||
|
|
- 请求体字段与校验规则
|
|||
|
|
- 响应格式与错误码
|
|||
|
|
- 验证码机制与防暴力注册策略
|
|||
|
|
- 密码加密存储流程
|
|||
|
|
- 安全建议(密码强度、邮箱格式、防暴力注册)
|
|||
|
|
|
|||
|
|
## 项目结构
|
|||
|
|
该功能由 Handler 层接收请求、Service 层执行业务逻辑、Model 层承载数据模型,并通过 JWT 生成登录令牌;验证码由 Redis 缓存并在邮件服务中发送。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph TB
|
|||
|
|
Client["客户端"] --> Routes["路由: /api/v1/auth/register"]
|
|||
|
|
Routes --> Handler["处理器: Register"]
|
|||
|
|
Handler --> VerifyCode["验证码校验: VerifyCode"]
|
|||
|
|
Handler --> UserService["服务: RegisterUser"]
|
|||
|
|
UserService --> Password["密码加密: HashPassword"]
|
|||
|
|
UserService --> ModelUser["用户模型: User"]
|
|||
|
|
UserService --> JWT["JWT 服务: GenerateToken"]
|
|||
|
|
Handler --> Response["统一响应: Response/ErrorResponse"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [routes.go](file://internal/handler/routes.go#L16-L26)
|
|||
|
|
- [auth_handler.go](file://internal/handler/auth_handler.go#L17-L84)
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go#L79-L98)
|
|||
|
|
- [user_service.go](file://internal/service/user_service.go#L12-L68)
|
|||
|
|
- [password.go](file://pkg/auth/password.go#L7-L21)
|
|||
|
|
- [user.go](file://internal/model/user.go#L7-L21)
|
|||
|
|
- [response.go](file://internal/model/response.go#L20-L73)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [routes.go](file://internal/handler/routes.go#L16-L26)
|
|||
|
|
|
|||
|
|
## 核心组件
|
|||
|
|
- 路由与入口
|
|||
|
|
- 路由位于 v1 组下的 /auth/register,无需 JWT 即可访问。
|
|||
|
|
- 请求体与校验
|
|||
|
|
- 请求体字段:username、email、password、avatar、verification_code。
|
|||
|
|
- 校验规则:必填、长度/格式约束、验证码长度固定为6。
|
|||
|
|
- 业务处理
|
|||
|
|
- 验证码校验通过后,检查用户名/邮箱唯一性,加密密码,创建用户并生成 JWT。
|
|||
|
|
- 响应与错误
|
|||
|
|
- 成功返回包含 token 与用户信息的结构化响应;常见错误包括参数错误、验证码错误、用户名/邮箱已存在等。
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [auth_handler.go](file://internal/handler/auth_handler.go#L17-L84)
|
|||
|
|
- [common.go](file://internal/types/common.go#L33-L40)
|
|||
|
|
- [response.go](file://internal/model/response.go#L20-L73)
|
|||
|
|
- [user_service.go](file://internal/service/user_service.go#L12-L68)
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go#L79-L98)
|
|||
|
|
|
|||
|
|
## 架构总览
|
|||
|
|
注册流程的端到端调用序列如下:
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant C as "客户端"
|
|||
|
|
participant R as "路由"
|
|||
|
|
participant H as "处理器 : Register"
|
|||
|
|
participant VS as "验证码服务 : VerifyCode"
|
|||
|
|
participant US as "用户服务 : RegisterUser"
|
|||
|
|
participant PS as "密码服务 : HashPassword"
|
|||
|
|
participant M as "用户模型 : User"
|
|||
|
|
participant JS as "JWT服务 : GenerateToken"
|
|||
|
|
participant RESP as "响应"
|
|||
|
|
C->>R : POST /api/v1/auth/register
|
|||
|
|
R->>H : 转发请求
|
|||
|
|
H->>H : 解析并绑定请求体
|
|||
|
|
H->>VS : 校验邮箱验证码
|
|||
|
|
VS-->>H : 验证通过/失败
|
|||
|
|
alt 验证失败
|
|||
|
|
H-->>RESP : 返回400错误
|
|||
|
|
else 验证通过
|
|||
|
|
H->>US : 调用注册流程
|
|||
|
|
US->>US : 检查用户名/邮箱唯一性
|
|||
|
|
US->>PS : 加密密码
|
|||
|
|
PS-->>US : 密文
|
|||
|
|
US->>M : 创建用户记录
|
|||
|
|
US->>JS : 生成JWT
|
|||
|
|
JS-->>US : token
|
|||
|
|
US-->>H : 返回用户与token
|
|||
|
|
H-->>RESP : 返回200成功响应
|
|||
|
|
end
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [auth_handler.go](file://internal/handler/auth_handler.go#L27-L84)
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go#L79-L98)
|
|||
|
|
- [user_service.go](file://internal/service/user_service.go#L12-L68)
|
|||
|
|
- [password.go](file://pkg/auth/password.go#L7-L21)
|
|||
|
|
- [user.go](file://internal/model/user.go#L7-L21)
|
|||
|
|
- [response.go](file://internal/model/response.go#L20-L73)
|
|||
|
|
|
|||
|
|
## 详细组件分析
|
|||
|
|
|
|||
|
|
### 接口定义与请求体
|
|||
|
|
- 端点:POST /api/v1/auth/register
|
|||
|
|
- 请求体字段
|
|||
|
|
- username:必填,长度3~50
|
|||
|
|
- email:必填,邮箱格式
|
|||
|
|
- password:必填,长度6~128
|
|||
|
|
- avatar:可选,URL格式
|
|||
|
|
- verification_code:必填,长度6
|
|||
|
|
- 响应
|
|||
|
|
- 成功:返回包含 token 与用户信息的结构化响应
|
|||
|
|
- 失败:返回统一错误响应,包含业务码与消息
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [auth_handler.go](file://internal/handler/auth_handler.go#L17-L84)
|
|||
|
|
- [common.go](file://internal/types/common.go#L33-L40)
|
|||
|
|
- [response.go](file://internal/model/response.go#L20-L73)
|
|||
|
|
|
|||
|
|
### 验证码机制与防暴力注册
|
|||
|
|
- 验证码生成与存储
|
|||
|
|
- 生成6位数字验证码,有效期10分钟,发送频率限制1分钟。
|
|||
|
|
- 存储于 Redis,键命名包含类型与邮箱。
|
|||
|
|
- 验证流程
|
|||
|
|
- 校验验证码是否存在且一致,一致即删除该验证码。
|
|||
|
|
- 防暴力注册
|
|||
|
|
- 发送频率限制键存在即拒绝重复发送,降低刷验证码风险。
|
|||
|
|
- 注册接口对用户名/邮箱唯一性检查,避免重复注册。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TD
|
|||
|
|
Start(["开始"]) --> Gen["生成6位验证码"]
|
|||
|
|
Gen --> Store["写入Redis: 验证码键(10分钟)"]
|
|||
|
|
Store --> RateLimit["写入Redis: 发送频率限制键(1分钟)"]
|
|||
|
|
RateLimit --> Email["发送邮件"]
|
|||
|
|
Email --> Verify["校验验证码"]
|
|||
|
|
Verify --> Match{"是否匹配?"}
|
|||
|
|
Match --> |否| Expired["返回错误: 验证码错误/过期"]
|
|||
|
|
Match --> |是| Del["删除验证码键"]
|
|||
|
|
Del --> Done(["结束"])
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go#L26-L98)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go#L14-L24)
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go#L40-L77)
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go#L79-L98)
|
|||
|
|
|
|||
|
|
### 密码加密与存储
|
|||
|
|
- 加密方式:bcrypt,默认成本
|
|||
|
|
- 存储:用户密码以密文形式保存,不返回明文
|
|||
|
|
- 登录校验:使用 bcrypt 对比哈希
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TD
|
|||
|
|
In(["输入明文密码"]) --> Hash["bcrypt加密"]
|
|||
|
|
Hash --> Out(["返回密文"])
|
|||
|
|
Out --> Store["持久化存储"]
|
|||
|
|
Store --> Login["登录时对比哈希"]
|
|||
|
|
Login --> Ok["匹配成功"]
|
|||
|
|
Login --> Fail["匹配失败"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [password.go](file://pkg/auth/password.go#L7-L21)
|
|||
|
|
- [user_service.go](file://internal/service/user_service.go#L32-L36)
|
|||
|
|
- [user.go](file://internal/model/user.go#L7-L21)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [password.go](file://pkg/auth/password.go#L7-L21)
|
|||
|
|
- [user_service.go](file://internal/service/user_service.go#L32-L36)
|
|||
|
|
- [user.go](file://internal/model/user.go#L7-L21)
|
|||
|
|
|
|||
|
|
### 用户模型与唯一性约束
|
|||
|
|
- 用户模型包含:id、username、password、email、avatar、points、role、status、属性、登录时间、创建/更新时间等
|
|||
|
|
- 唯一性约束:username 与 email 在数据库层面唯一索引
|
|||
|
|
- 注册时:若用户名或邮箱已存在,返回错误
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
erDiagram
|
|||
|
|
USER {
|
|||
|
|
bigint id PK
|
|||
|
|
varchar username UK
|
|||
|
|
varchar password
|
|||
|
|
varchar email UK
|
|||
|
|
varchar avatar
|
|||
|
|
integer points
|
|||
|
|
varchar role
|
|||
|
|
smallint status
|
|||
|
|
jsonb properties
|
|||
|
|
timestamp last_login_at
|
|||
|
|
timestamp created_at
|
|||
|
|
timestamp updated_at
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [user.go](file://internal/model/user.go#L7-L21)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [user.go](file://internal/model/user.go#L7-L21)
|
|||
|
|
- [user_service.go](file://internal/service/user_service.go#L14-L31)
|
|||
|
|
|
|||
|
|
### 错误码与响应格式
|
|||
|
|
- 成功:200,返回结构化响应,包含 token 与用户信息
|
|||
|
|
- 参数错误:400,请求体绑定失败或字段校验失败
|
|||
|
|
- 验证码错误:400,验证码不存在/过期/不匹配
|
|||
|
|
- 资源冲突:409,用户名或邮箱已存在
|
|||
|
|
- 服务器错误:500,内部异常
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [auth_handler.go](file://internal/handler/auth_handler.go#L27-L84)
|
|||
|
|
- [response.go](file://internal/model/response.go#L20-L73)
|
|||
|
|
- [user_service.go](file://internal/service/user_service.go#L14-L31)
|
|||
|
|
|
|||
|
|
### 安全考虑与最佳实践
|
|||
|
|
- 密码强度
|
|||
|
|
- 至少6位,建议结合复杂度策略(字母、数字、特殊字符)
|
|||
|
|
- 使用 bcrypt 存储,避免明文或弱加密
|
|||
|
|
- 邮箱格式验证
|
|||
|
|
- 使用框架内置邮箱格式校验
|
|||
|
|
- 防暴力注册
|
|||
|
|
- 验证码发送频率限制(1分钟)
|
|||
|
|
- 验证码有效期(10分钟),过期自动失效
|
|||
|
|
- 唯一性检查防止重复注册
|
|||
|
|
- 传输安全
|
|||
|
|
- 建议启用 HTTPS,避免明文传输
|
|||
|
|
- 日志与审计
|
|||
|
|
- 记录注册失败与异常行为,便于追踪
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go#L14-L24)
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go#L40-L77)
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go#L79-L98)
|
|||
|
|
- [user_service.go](file://internal/service/user_service.go#L14-L31)
|
|||
|
|
- [password.go](file://pkg/auth/password.go#L7-L21)
|
|||
|
|
|
|||
|
|
## 依赖关系分析
|
|||
|
|
- 处理器依赖
|
|||
|
|
- 验证码服务:用于校验注册验证码
|
|||
|
|
- 用户服务:执行注册流程(唯一性检查、密码加密、创建用户、生成JWT)
|
|||
|
|
- JWT 服务:生成登录令牌
|
|||
|
|
- 服务依赖
|
|||
|
|
- 密码服务:bcrypt 加密与校验
|
|||
|
|
- 数据模型:用户实体
|
|||
|
|
- 工具与中间件
|
|||
|
|
- 路由:定义 /api/v1/auth/register
|
|||
|
|
- 统一响应:封装业务码与消息
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph LR
|
|||
|
|
Handler["处理器: Register"] --> VS["验证码服务: VerifyCode"]
|
|||
|
|
Handler --> US["用户服务: RegisterUser"]
|
|||
|
|
US --> PS["密码服务: HashPassword"]
|
|||
|
|
US --> Model["用户模型: User"]
|
|||
|
|
US --> JWT["JWT服务: GenerateToken"]
|
|||
|
|
Handler --> Resp["统一响应: Response/ErrorResponse"]
|
|||
|
|
Route["路由: /api/v1/auth/register"] --> Handler
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [auth_handler.go](file://internal/handler/auth_handler.go#L27-L84)
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go#L79-L98)
|
|||
|
|
- [user_service.go](file://internal/service/user_service.go#L12-L68)
|
|||
|
|
- [password.go](file://pkg/auth/password.go#L7-L21)
|
|||
|
|
- [user.go](file://internal/model/user.go#L7-L21)
|
|||
|
|
- [response.go](file://internal/model/response.go#L20-L73)
|
|||
|
|
- [routes.go](file://internal/handler/routes.go#L16-L26)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [auth_handler.go](file://internal/handler/auth_handler.go#L27-L84)
|
|||
|
|
- [user_service.go](file://internal/service/user_service.go#L12-L68)
|
|||
|
|
- [verification_service.go](file://internal/service/verification_service.go#L79-L98)
|
|||
|
|
- [password.go](file://pkg/auth/password.go#L7-L21)
|
|||
|
|
- [user.go](file://internal/model/user.go#L7-L21)
|
|||
|
|
- [response.go](file://internal/model/response.go#L20-L73)
|
|||
|
|
- [routes.go](file://internal/handler/routes.go#L16-L26)
|
|||
|
|
|
|||
|
|
## 性能与扩展性
|
|||
|
|
- 验证码缓存
|
|||
|
|
- Redis 存储验证码与频率限制,具备高并发与低延迟特性
|
|||
|
|
- 密码加密
|
|||
|
|
- bcrypt 默认成本在安全性与性能间平衡,可根据硬件能力调整
|
|||
|
|
- 扩展建议
|
|||
|
|
- 引入速率限制中间件,对 /api/v1/auth/register 进一步限流
|
|||
|
|
- 增加 IP/设备维度的风控策略
|
|||
|
|
- 对高频失败场景增加验证码挑战或人机验证
|
|||
|
|
|
|||
|
|
[本节为通用建议,不直接分析具体文件]
|
|||
|
|
|
|||
|
|
## 故障排查指南
|
|||
|
|
- 常见错误与定位
|
|||
|
|
- 参数错误:检查请求体字段是否满足长度/格式要求
|
|||
|
|
- 验证码错误:确认验证码是否过期、是否与发送邮箱一致
|
|||
|
|
- 用户名/邮箱已存在:检查数据库唯一性约束
|
|||
|
|
- 单元测试参考
|
|||
|
|
- 注册请求体校验、错误处理与响应格式可通过测试用例验证
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [auth_handler_test.go](file://internal/handler/auth_handler_test.go#L74-L116)
|
|||
|
|
- [common_test.go](file://internal/types/common_test.go#L215-L287)
|
|||
|
|
|
|||
|
|
## 结论
|
|||
|
|
用户注册 API 通过严格的请求体校验、验证码机制与 bcrypt 密码加密,提供了基础的安全保障。配合唯一性检查与频率限制,能够有效降低重复注册与暴力注册的风险。建议在生产环境中进一步完善风控策略与监控告警体系。
|
|||
|
|
|
|||
|
|
[本节为总结性内容,不直接分析具体文件]
|
|||
|
|
|
|||
|
|
## 附录
|
|||
|
|
|
|||
|
|
### 请求与响应示例(路径引用)
|
|||
|
|
- 请求体字段与校验规则
|
|||
|
|
- 字段定义与校验规则参见:[请求体定义](file://internal/types/common.go#L33-L40)
|
|||
|
|
- 成功响应结构
|
|||
|
|
- 成功响应结构参见:[统一响应](file://internal/model/response.go#L20-L73)
|
|||
|
|
- 登录响应结构参见:[登录响应](file://internal/types/common.go#L107-L126)
|
|||
|
|
- 错误响应结构
|
|||
|
|
- 错误响应结构参见:[错误响应](file://internal/model/response.go#L20-L73)
|
|||
|
|
- 路由与端点
|
|||
|
|
- 注册路由参见:[路由定义](file://internal/handler/routes.go#L16-L26)
|
|||
|
|
- 处理器与业务流程
|
|||
|
|
- 注册处理器参见:[注册处理器](file://internal/handler/auth_handler.go#L27-L84)
|
|||
|
|
- 注册业务流程参见:[注册服务](file://internal/service/user_service.go#L12-L68)
|
|||
|
|
- 验证码与防暴力
|
|||
|
|
- 验证码生成与校验参见:[验证码服务](file://internal/service/verification_service.go#L26-L98)
|
|||
|
|
- 密码加密
|
|||
|
|
- 密码加密与校验参见:[密码服务](file://pkg/auth/password.go#L7-L21)
|