17 KiB
17 KiB
用户API
**本文引用的文件** - [internal/handler/routes.go](file://internal/handler/routes.go) - [internal/middleware/auth.go](file://internal/middleware/auth.go) - [internal/handler/user_handler.go](file://internal/handler/user_handler.go) - [internal/service/user_service.go](file://internal/service/user_service.go) - [internal/service/upload_service.go](file://internal/service/upload_service.go) - [internal/service/verification_service.go](file://internal/service/verification_service.go) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go) - [internal/types/common.go](file://internal/types/common.go) - [internal/model/response.go](file://internal/model/response.go) - [internal/model/user.go](file://internal/model/user.go) - [pkg/auth/jwt.go](file://pkg/auth/jwt.go) - [pkg/storage/minio.go](file://pkg/storage/minio.go) - [pkg/config/config.go](file://pkg/config/config.go)目录
简介
本文件面向开发者与集成方,系统化梳理用户管理API,覆盖以下能力:
- 获取与更新用户个人资料
- 更换邮箱(基于验证码)
- 头像上传(通过预签名URL)
- JWT认证中间件的工作机制
- 数据结构、请求/响应模式、错误处理与常见问题
项目结构
用户相关接口位于统一的路由组“/api/v1/user”,该组下所有端点均受JWT认证保护。认证中间件负责从请求头中提取并校验Bearer Token,并将用户标识写入上下文供业务层使用。
graph TB
Client["客户端"] --> Routes["路由注册<br/>/api/v1/user/*"]
Routes --> AuthMW["认证中间件<br/>AuthMiddleware()"]
AuthMW --> Handlers["用户处理器<br/>user_handler.go"]
Handlers --> Services["用户服务<br/>user_service.go"]
Services --> Repos["用户仓储<br/>user_repository.go"]
Services --> UploadSvc["上传服务<br/>upload_service.go"]
UploadSvc --> Storage["对象存储客户端<br/>minio.go"]
Services --> VeriSvc["验证码服务<br/>verification_service.go"]
Services --> JWT["JWT服务<br/>jwt.go"]
Services --> Types["类型定义<br/>types/common.go"]
Handlers --> Models["响应模型<br/>response.go"]
Handlers --> UserModel["用户模型<br/>model/user.go"]
图表来源
- internal/handler/routes.go
- internal/middleware/auth.go
- internal/handler/user_handler.go
- internal/service/user_service.go
- internal/service/upload_service.go
- pkg/storage/minio.go
- pkg/auth/jwt.go
- internal/types/common.go
- internal/model/response.go
- internal/model/user.go
章节来源
核心组件
- 路由与认证
- 路由组“/api/v1/user”下的所有端点均使用认证中间件保护。
- 中间件从Authorization头解析Bearer Token,调用JWT服务进行校验,并将用户ID、用户名、角色写入上下文。
- 用户处理器
- 提供获取/更新用户资料、生成头像上传URL、更新头像、更换邮箱等接口。
- 服务层
- 用户服务封装业务逻辑(如修改密码、更换邮箱、更新头像),并调用仓储层持久化。
- 上传服务负责生成预签名URL(POST策略),并构造最终可访问的文件URL。
- 验证码服务负责生成、发送与校验验证码(更换邮箱场景)。
- 仓储层
- 提供用户查询、更新、软删除等基础操作。
- 类型与模型
- 统一响应结构、用户信息结构、请求参数结构等。
- 用户模型包含基本字段及JSONB属性字段。
章节来源
- internal/handler/routes.go
- internal/middleware/auth.go
- internal/handler/user_handler.go
- internal/service/user_service.go
- internal/service/upload_service.go
- internal/service/verification_service.go
- internal/repository/user_repository.go
- internal/types/common.go
- internal/model/response.go
- internal/model/user.go
架构总览
用户API采用“路由-中间件-处理器-服务-仓储-存储/外部服务”的分层架构。JWT中间件贯穿所有用户相关端点,确保只有合法令牌才能访问。
sequenceDiagram
participant C as "客户端"
participant R as "路由(/api/v1/user/*)"
participant M as "认证中间件"
participant H as "用户处理器"
participant S as "用户服务"
participant U as "上传服务"
participant V as "验证码服务"
participant D as "仓储"
participant T as "JWT服务"
participant O as "对象存储"
C->>R : "携带Authorization : Bearer <token>"
R->>M : "进入中间件"
M->>T : "校验token"
T-->>M : "Claims(用户ID/用户名/角色)"
M->>H : "放行,写入上下文"
alt 获取/更新资料
H->>S : "GetUserByID/UpdateUserInfo"
S->>D : "查询/更新"
D-->>S : "结果"
S-->>H : "用户信息"
H-->>C : "200 成功响应"
else 生成头像上传URL
H->>U : "GenerateAvatarUploadURL"
U->>O : "生成预签名POST策略"
O-->>U : "PostURL+FormData+FileURL"
U-->>H : "结果"
H-->>C : "200 成功响应"
else 更换邮箱
H->>V : "VerifyCode(验证码)"
V-->>H : "校验通过/失败"
H->>S : "ChangeUserEmail"
S->>D : "更新邮箱"
D-->>S : "结果"
S-->>H : "用户信息"
H-->>C : "200 成功响应"
end
图表来源
- internal/handler/routes.go
- internal/middleware/auth.go
- internal/handler/user_handler.go
- internal/service/user_service.go
- internal/service/upload_service.go
- internal/service/verification_service.go
- internal/repository/user_repository.go
- pkg/auth/jwt.go
- pkg/storage/minio.go
详细组件分析
认证中间件 AuthMiddleware
- 功能
- 从请求头Authorization中解析Bearer token
- 调用JWT服务校验token有效性
- 校验通过后将用户ID、用户名、角色写入上下文,供后续处理器使用
- 异常
- 缺少Authorization头、格式不正确、token无效时返回401
- 适用范围
- 所有“/api/v1/user/*”端点均受此中间件保护
章节来源
用户资料:获取与更新
- 获取用户资料
- 方法:GET /api/v1/user/profile
- 认证:需要Bearer token
- 成功响应:包含用户基本信息(ID、用户名、邮箱、头像、积分、角色、状态、时间戳等)
- 错误:未授权、用户不存在
- 更新用户资料
- 方法:PUT /api/v1/user/profile
- 认证:需要Bearer token
- 请求体:支持更新头像URL;若提供新密码,必须同时提供旧密码
- 成功响应:返回更新后的用户信息
- 错误:参数错误、未授权、服务器错误、用户不存在
章节来源
- internal/handler/user_handler.go
- internal/types/common.go
- internal/model/response.go
- internal/model/user.go
头像上传流程(预签名URL)
- 生成上传URL
- 方法:POST /api/v1/user/avatar/upload-url
- 认证:需要Bearer token
- 请求体:文件名(file_name)
- 成功响应:包含PostURL、FormData、AvatarURL、过期秒数(ExpiresIn)
- 错误:参数错误、未授权、生成URL失败
- 上传与确认
- 客户端使用返回的PostURL与FormData直传至对象存储
- 上传完成后调用PUT /api/v1/user/avatar,携带avatar_url查询参数
- 服务端更新用户头像字段并返回最新用户信息
sequenceDiagram
participant C as "客户端"
participant H as "用户处理器"
participant U as "上传服务"
participant S as "对象存储客户端"
participant D as "仓储"
C->>H : "POST /api/v1/user/avatar/upload-url {file_name}"
H->>U : "GenerateAvatarUploadURL(userID, file_name)"
U->>S : "生成预签名POST策略"
S-->>U : "PostURL+FormData+FileURL"
U-->>H : "返回结果"
H-->>C : "200 {post_url, form_data, avatar_url, expires_in}"
C->>S : "使用PostURL+FormData直传"
S-->>C : "204/201"
C->>H : "PUT /api/v1/user/avatar?avatar_url=..."
H->>D : "UpdateUserAvatar"
D-->>H : "成功"
H-->>C : "200 用户信息"
图表来源
- internal/handler/user_handler.go
- internal/service/upload_service.go
- pkg/storage/minio.go
- internal/repository/user_repository.go
章节来源
- internal/handler/user_handler.go
- internal/service/upload_service.go
- pkg/storage/minio.go
- internal/repository/user_repository.go
更换邮箱(验证码)
- 流程
- 客户端先向验证码服务发送验证码(此处为通用流程,更换邮箱场景使用特定类型)
- 调用POST /api/v1/user/change-email,携带新邮箱与验证码
- 服务端校验验证码,通过后更新用户邮箱并返回最新用户信息
- 请求体
- 新邮箱(new_email)
- 验证码(verification_code)
- 成功/错误
- 成功:返回用户信息
- 错误:参数错误、未授权、验证码错误、邮箱已被占用等
章节来源
- internal/handler/user_handler.go
- internal/service/verification_service.go
- internal/service/user_service.go
- internal/repository/user_repository.go
数据结构与请求/响应模式
- 用户信息结构(UserInfo)
- 字段:id、username、email、avatar、points、role、status、last_login_at、created_at、updated_at
- 请求体
- 更新用户:UpdateUserRequest(avatar、old_password、new_password)
- 生成头像上传URL:GenerateAvatarUploadURLRequest(file_name)
- 更换邮箱:ChangeEmailRequest(new_email、verification_code)
- 通用响应
- 成功:code=200,message=“操作成功”,data为具体数据
- 失败:code为对应HTTP语义码,message为错误描述,开发环境可带error字段
章节来源
- internal/types/common.go
- internal/types/common.go
- internal/types/common.go
- internal/model/response.go
- internal/model/user.go
依赖关系分析
- 路由到处理器
- /api/v1/user/profile GET/PUT -> GetUserProfile/UpdateUserProfile
- /api/v1/user/avatar/upload-url POST -> GenerateAvatarUploadURL
- /api/v1/user/avatar PUT -> UpdateAvatar
- /api/v1/user/change-email POST -> ChangeEmail
- 处理器到服务
- 用户处理器调用用户服务、上传服务、验证码服务
- 服务到仓储/存储
- 用户服务调用仓储更新用户信息
- 上传服务调用对象存储客户端生成预签名URL
- 中间件到JWT
- 认证中间件依赖JWT服务校验token并注入用户上下文
graph LR
Routes["routes.go"] --> Handler["user_handler.go"]
Handler --> UserService["user_service.go"]
Handler --> UploadService["upload_service.go"]
Handler --> VeriService["verification_service.go"]
UserService --> Repo["user_repository.go"]
UploadService --> Storage["minio.go"]
Handler --> Types["types/common.go"]
Handler --> Resp["response.go"]
Handler --> ModelUser["model/user.go"]
AuthMW["auth.go"] --> JWT["jwt.go"]
Handler --> AuthMW
图表来源
- internal/handler/routes.go
- internal/handler/user_handler.go
- internal/service/user_service.go
- internal/service/upload_service.go
- internal/service/verification_service.go
- internal/repository/user_repository.go
- internal/types/common.go
- internal/model/response.go
- internal/model/user.go
- internal/middleware/auth.go
- pkg/auth/jwt.go
- pkg/storage/minio.go
性能与安全考量
- 性能
- 上传采用预签名POST策略,避免服务端中转,降低带宽与延迟
- 对象存储客户端连接复用,建议合理配置RustFS/Buckets与连接参数
- 安全
- 所有用户相关端点强制JWT认证
- 上传URL带过期时间,防止长期有效链接泄露
- 验证码更换邮箱,避免暴力破解
- 密码修改需提供旧密码,防止越权修改
- 可靠性
- 上传URL生成失败、验证码校验失败、仓储更新失败均有明确错误返回
- 建议对高频接口增加限流与熔断策略(可在网关或中间件层实现)
[本节为通用指导,不直接分析具体文件]
故障排查指南
- 401 未授权
- 检查Authorization头是否为Bearer token格式
- 确认token未过期且签名正确
- 400 参数错误
- 检查请求体字段是否符合约束(如邮箱格式、验证码长度、文件名等)
- 404 用户不存在
- 确认用户ID有效且未被软删除
- 上传失败
- 检查生成的PostURL与FormData是否完整
- 确认对象存储端点、证书、桶名配置正确
- 验证码错误
- 检查Redis中验证码是否过期或被提前消费
- 确认发送频率限制未触发
章节来源
- internal/handler/user_handler.go
- internal/service/verification_service.go
- pkg/storage/minio.go
- pkg/config/config.go
结论
本文档系统梳理了用户管理API的路由、认证、数据结构与流程,明确了头像上传与邮箱更换的关键步骤与错误处理策略。建议在生产环境中结合限流、监控与日志体系,持续优化用户体验与系统稳定性。
[本节为总结,不直接分析具体文件]
附录
接口一览与示例
- 获取用户资料
- 方法:GET /api/v1/user/profile
- 请求:Authorization: Bearer
- 成功响应:包含UserInfo
- 更新用户资料
- 方法:PUT /api/v1/user/profile
- 请求体:UpdateUserRequest(avatar、old_password、new_password)
- 成功响应:包含更新后的UserInfo
- 生成头像上传URL
- 方法:POST /api/v1/user/avatar/upload-url
- 请求体:GenerateAvatarUploadURLRequest(file_name)
- 成功响应:包含post_url、form_data、avatar_url、expires_in
- 上传头像并确认
- 方法:PUT /api/v1/user/avatar?avatar_url=...
- 成功响应:包含UserInfo
- 更换邮箱
- 方法:POST /api/v1/user/change-email
- 请求体:ChangeEmailRequest(new_email、verification_code)
- 成功响应:包含UserInfo
章节来源