# 用户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) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能与安全考量](#性能与安全考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件面向开发者与集成方,系统化梳理用户管理API,覆盖以下能力: - 获取与更新用户个人资料 - 更换邮箱(基于验证码) - 头像上传(通过预签名URL) - JWT认证中间件的工作机制 - 数据结构、请求/响应模式、错误处理与常见问题 ## 项目结构 用户相关接口位于统一的路由组“/api/v1/user”,该组下所有端点均受JWT认证保护。认证中间件负责从请求头中提取并校验Bearer Token,并将用户标识写入上下文供业务层使用。 ```mermaid graph TB Client["客户端"] --> Routes["路由注册
/api/v1/user/*"] Routes --> AuthMW["认证中间件
AuthMiddleware()"] AuthMW --> Handlers["用户处理器
user_handler.go"] Handlers --> Services["用户服务
user_service.go"] Services --> Repos["用户仓储
user_repository.go"] Services --> UploadSvc["上传服务
upload_service.go"] UploadSvc --> Storage["对象存储客户端
minio.go"] Services --> VeriSvc["验证码服务
verification_service.go"] Services --> JWT["JWT服务
jwt.go"] Services --> Types["类型定义
types/common.go"] Handlers --> Models["响应模型
response.go"] Handlers --> UserModel["用户模型
model/user.go"] ``` 图表来源 - [internal/handler/routes.go](file://internal/handler/routes.go#L16-L41) - [internal/middleware/auth.go](file://internal/middleware/auth.go#L12-L56) - [internal/handler/user_handler.go](file://internal/handler/user_handler.go#L17-L416) - [internal/service/user_service.go](file://internal/service/user_service.go#L1-L249) - [internal/service/upload_service.go](file://internal/service/upload_service.go#L1-L161) - [pkg/storage/minio.go](file://pkg/storage/minio.go#L1-L121) - [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L1-L71) - [internal/types/common.go](file://internal/types/common.go#L1-L215) - [internal/model/response.go](file://internal/model/response.go#L1-L86) - [internal/model/user.go](file://internal/model/user.go#L1-L71) 章节来源 - [internal/handler/routes.go](file://internal/handler/routes.go#L16-L41) ## 核心组件 - 路由与认证 - 路由组“/api/v1/user”下的所有端点均使用认证中间件保护。 - 中间件从Authorization头解析Bearer Token,调用JWT服务进行校验,并将用户ID、用户名、角色写入上下文。 - 用户处理器 - 提供获取/更新用户资料、生成头像上传URL、更新头像、更换邮箱等接口。 - 服务层 - 用户服务封装业务逻辑(如修改密码、更换邮箱、更新头像),并调用仓储层持久化。 - 上传服务负责生成预签名URL(POST策略),并构造最终可访问的文件URL。 - 验证码服务负责生成、发送与校验验证码(更换邮箱场景)。 - 仓储层 - 提供用户查询、更新、软删除等基础操作。 - 类型与模型 - 统一响应结构、用户信息结构、请求参数结构等。 - 用户模型包含基本字段及JSONB属性字段。 章节来源 - [internal/handler/routes.go](file://internal/handler/routes.go#L16-L41) - [internal/middleware/auth.go](file://internal/middleware/auth.go#L12-L56) - [internal/handler/user_handler.go](file://internal/handler/user_handler.go#L17-L416) - [internal/service/user_service.go](file://internal/service/user_service.go#L1-L249) - [internal/service/upload_service.go](file://internal/service/upload_service.go#L1-L161) - [internal/service/verification_service.go](file://internal/service/verification_service.go#L1-L119) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L1-L137) - [internal/types/common.go](file://internal/types/common.go#L1-L215) - [internal/model/response.go](file://internal/model/response.go#L1-L86) - [internal/model/user.go](file://internal/model/user.go#L1-L71) ## 架构总览 用户API采用“路由-中间件-处理器-服务-仓储-存储/外部服务”的分层架构。JWT中间件贯穿所有用户相关端点,确保只有合法令牌才能访问。 ```mermaid 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 " 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](file://internal/handler/routes.go#L16-L41) - [internal/middleware/auth.go](file://internal/middleware/auth.go#L12-L56) - [internal/handler/user_handler.go](file://internal/handler/user_handler.go#L17-L416) - [internal/service/user_service.go](file://internal/service/user_service.go#L1-L249) - [internal/service/upload_service.go](file://internal/service/upload_service.go#L1-L161) - [internal/service/verification_service.go](file://internal/service/verification_service.go#L1-L119) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L1-L137) - [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L1-L71) - [pkg/storage/minio.go](file://pkg/storage/minio.go#L1-L121) ## 详细组件分析 ### 认证中间件 AuthMiddleware - 功能 - 从请求头Authorization中解析Bearer token - 调用JWT服务校验token有效性 - 校验通过后将用户ID、用户名、角色写入上下文,供后续处理器使用 - 异常 - 缺少Authorization头、格式不正确、token无效时返回401 - 适用范围 - 所有“/api/v1/user/*”端点均受此中间件保护 章节来源 - [internal/middleware/auth.go](file://internal/middleware/auth.go#L12-L56) - [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L1-L71) ### 用户资料:获取与更新 - 获取用户资料 - 方法:GET /api/v1/user/profile - 认证:需要Bearer token - 成功响应:包含用户基本信息(ID、用户名、邮箱、头像、积分、角色、状态、时间戳等) - 错误:未授权、用户不存在 - 更新用户资料 - 方法:PUT /api/v1/user/profile - 认证:需要Bearer token - 请求体:支持更新头像URL;若提供新密码,必须同时提供旧密码 - 成功响应:返回更新后的用户信息 - 错误:参数错误、未授权、服务器错误、用户不存在 章节来源 - [internal/handler/user_handler.go](file://internal/handler/user_handler.go#L17-L193) - [internal/types/common.go](file://internal/types/common.go#L42-L47) - [internal/model/response.go](file://internal/model/response.go#L1-L86) - [internal/model/user.go](file://internal/model/user.go#L1-L21) ### 头像上传流程(预签名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查询参数 - 服务端更新用户头像字段并返回最新用户信息 ```mermaid 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](file://internal/handler/user_handler.go#L195-L326) - [internal/service/upload_service.go](file://internal/service/upload_service.go#L1-L161) - [pkg/storage/minio.go](file://pkg/storage/minio.go#L1-L121) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L126-L130) 章节来源 - [internal/handler/user_handler.go](file://internal/handler/user_handler.go#L195-L326) - [internal/service/upload_service.go](file://internal/service/upload_service.go#L1-L161) - [pkg/storage/minio.go](file://pkg/storage/minio.go#L1-L121) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L126-L130) ### 更换邮箱(验证码) - 流程 - 客户端先向验证码服务发送验证码(此处为通用流程,更换邮箱场景使用特定类型) - 调用POST /api/v1/user/change-email,携带新邮箱与验证码 - 服务端校验验证码,通过后更新用户邮箱并返回最新用户信息 - 请求体 - 新邮箱(new_email) - 验证码(verification_code) - 成功/错误 - 成功:返回用户信息 - 错误:参数错误、未授权、验证码错误、邮箱已被占用等 章节来源 - [internal/handler/user_handler.go](file://internal/handler/user_handler.go#L328-L416) - [internal/service/verification_service.go](file://internal/service/verification_service.go#L1-L119) - [internal/service/user_service.go](file://internal/service/user_service.go#L186-L201) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L45-L57) ### 数据结构与请求/响应模式 - 用户信息结构(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](file://internal/types/common.go#L42-L47) - [internal/types/common.go](file://internal/types/common.go#L62-L67) - [internal/types/common.go](file://internal/types/common.go#L68-L80) - [internal/model/response.go](file://internal/model/response.go#L1-L86) - [internal/model/user.go](file://internal/model/user.go#L1-L21) ## 依赖关系分析 - 路由到处理器 - /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并注入用户上下文 ```mermaid 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](file://internal/handler/routes.go#L16-L41) - [internal/handler/user_handler.go](file://internal/handler/user_handler.go#L17-L416) - [internal/service/user_service.go](file://internal/service/user_service.go#L1-L249) - [internal/service/upload_service.go](file://internal/service/upload_service.go#L1-L161) - [internal/service/verification_service.go](file://internal/service/verification_service.go#L1-L119) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L1-L137) - [internal/types/common.go](file://internal/types/common.go#L1-L215) - [internal/model/response.go](file://internal/model/response.go#L1-L86) - [internal/model/user.go](file://internal/model/user.go#L1-L71) - [internal/middleware/auth.go](file://internal/middleware/auth.go#L12-L56) - [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L1-L71) - [pkg/storage/minio.go](file://pkg/storage/minio.go#L1-L121) ## 性能与安全考量 - 性能 - 上传采用预签名POST策略,避免服务端中转,降低带宽与延迟 - 对象存储客户端连接复用,建议合理配置RustFS/Buckets与连接参数 - 安全 - 所有用户相关端点强制JWT认证 - 上传URL带过期时间,防止长期有效链接泄露 - 验证码更换邮箱,避免暴力破解 - 密码修改需提供旧密码,防止越权修改 - 可靠性 - 上传URL生成失败、验证码校验失败、仓储更新失败均有明确错误返回 - 建议对高频接口增加限流与熔断策略(可在网关或中间件层实现) [本节为通用指导,不直接分析具体文件] ## 故障排查指南 - 401 未授权 - 检查Authorization头是否为Bearer token格式 - 确认token未过期且签名正确 - 400 参数错误 - 检查请求体字段是否符合约束(如邮箱格式、验证码长度、文件名等) - 404 用户不存在 - 确认用户ID有效且未被软删除 - 上传失败 - 检查生成的PostURL与FormData是否完整 - 确认对象存储端点、证书、桶名配置正确 - 验证码错误 - 检查Redis中验证码是否过期或被提前消费 - 确认发送频率限制未触发 章节来源 - [internal/handler/user_handler.go](file://internal/handler/user_handler.go#L17-L416) - [internal/service/verification_service.go](file://internal/service/verification_service.go#L1-L119) - [pkg/storage/minio.go](file://pkg/storage/minio.go#L1-L121) - [pkg/config/config.go](file://pkg/config/config.go#L1-L305) ## 结论 本文档系统梳理了用户管理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 章节来源 - [internal/handler/routes.go](file://internal/handler/routes.go#L16-L41) - [internal/handler/user_handler.go](file://internal/handler/user_handler.go#L17-L416) - [internal/types/common.go](file://internal/types/common.go#L42-L47) - [internal/types/common.go](file://internal/types/common.go#L62-L67) - [internal/types/common.go](file://internal/types/common.go#L68-L80)