13 KiB
13 KiB
用户注册
**本文引用的文件** - [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)目录
简介
本文件面向“用户注册”API,围绕 /api/v1/auth/register 端点进行完整说明。内容覆盖:
- HTTP 方法与路由
- 请求体字段与校验规则
- 响应格式与错误码
- 验证码机制与防暴力注册策略
- 密码加密存储流程
- 安全建议(密码强度、邮箱格式、防暴力注册)
项目结构
该功能由 Handler 层接收请求、Service 层执行业务逻辑、Model 层承载数据模型,并通过 JWT 生成登录令牌;验证码由 Redis 缓存并在邮件服务中发送。
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"]
图表来源
章节来源
核心组件
- 路由与入口
- 路由位于 v1 组下的 /auth/register,无需 JWT 即可访问。
- 请求体与校验
- 请求体字段:username、email、password、avatar、verification_code。
- 校验规则:必填、长度/格式约束、验证码长度固定为6。
- 业务处理
- 验证码校验通过后,检查用户名/邮箱唯一性,加密密码,创建用户并生成 JWT。
- 响应与错误
- 成功返回包含 token 与用户信息的结构化响应;常见错误包括参数错误、验证码错误、用户名/邮箱已存在等。
章节来源
架构总览
注册流程的端到端调用序列如下:
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
图表来源
详细组件分析
接口定义与请求体
- 端点:POST /api/v1/auth/register
- 请求体字段
- username:必填,长度3~50
- email:必填,邮箱格式
- password:必填,长度6~128
- avatar:可选,URL格式
- verification_code:必填,长度6
- 响应
- 成功:返回包含 token 与用户信息的结构化响应
- 失败:返回统一错误响应,包含业务码与消息
章节来源
验证码机制与防暴力注册
- 验证码生成与存储
- 生成6位数字验证码,有效期10分钟,发送频率限制1分钟。
- 存储于 Redis,键命名包含类型与邮箱。
- 验证流程
- 校验验证码是否存在且一致,一致即删除该验证码。
- 防暴力注册
- 发送频率限制键存在即拒绝重复发送,降低刷验证码风险。
- 注册接口对用户名/邮箱唯一性检查,避免重复注册。
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(["结束"])
图表来源
章节来源
密码加密与存储
- 加密方式:bcrypt,默认成本
- 存储:用户密码以密文形式保存,不返回明文
- 登录校验:使用 bcrypt 对比哈希
flowchart TD
In(["输入明文密码"]) --> Hash["bcrypt加密"]
Hash --> Out(["返回密文"])
Out --> Store["持久化存储"]
Store --> Login["登录时对比哈希"]
Login --> Ok["匹配成功"]
Login --> Fail["匹配失败"]
图表来源
章节来源
用户模型与唯一性约束
- 用户模型包含:id、username、password、email、avatar、points、role、status、属性、登录时间、创建/更新时间等
- 唯一性约束:username 与 email 在数据库层面唯一索引
- 注册时:若用户名或邮箱已存在,返回错误
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
}
图表来源
章节来源
错误码与响应格式
- 成功:200,返回结构化响应,包含 token 与用户信息
- 参数错误:400,请求体绑定失败或字段校验失败
- 验证码错误:400,验证码不存在/过期/不匹配
- 资源冲突:409,用户名或邮箱已存在
- 服务器错误:500,内部异常
章节来源
安全考虑与最佳实践
- 密码强度
- 至少6位,建议结合复杂度策略(字母、数字、特殊字符)
- 使用 bcrypt 存储,避免明文或弱加密
- 邮箱格式验证
- 使用框架内置邮箱格式校验
- 防暴力注册
- 验证码发送频率限制(1分钟)
- 验证码有效期(10分钟),过期自动失效
- 唯一性检查防止重复注册
- 传输安全
- 建议启用 HTTPS,避免明文传输
- 日志与审计
- 记录注册失败与异常行为,便于追踪
章节来源
依赖关系分析
- 处理器依赖
- 验证码服务:用于校验注册验证码
- 用户服务:执行注册流程(唯一性检查、密码加密、创建用户、生成JWT)
- JWT 服务:生成登录令牌
- 服务依赖
- 密码服务:bcrypt 加密与校验
- 数据模型:用户实体
- 工具与中间件
- 路由:定义 /api/v1/auth/register
- 统一响应:封装业务码与消息
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
图表来源
章节来源
性能与扩展性
- 验证码缓存
- Redis 存储验证码与频率限制,具备高并发与低延迟特性
- 密码加密
- bcrypt 默认成本在安全性与性能间平衡,可根据硬件能力调整
- 扩展建议
- 引入速率限制中间件,对 /api/v1/auth/register 进一步限流
- 增加 IP/设备维度的风控策略
- 对高频失败场景增加验证码挑战或人机验证
[本节为通用建议,不直接分析具体文件]
故障排查指南
- 常见错误与定位
- 参数错误:检查请求体字段是否满足长度/格式要求
- 验证码错误:确认验证码是否过期、是否与发送邮箱一致
- 用户名/邮箱已存在:检查数据库唯一性约束
- 单元测试参考
- 注册请求体校验、错误处理与响应格式可通过测试用例验证
章节来源
结论
用户注册 API 通过严格的请求体校验、验证码机制与 bcrypt 密码加密,提供了基础的安全保障。配合唯一性检查与频率限制,能够有效降低重复注册与暴力注册的风险。建议在生产环境中进一步完善风控策略与监控告警体系。
[本节为总结性内容,不直接分析具体文件]