# 用户管理系统架构设计文档 > 版本:v1.0 > 更新日期:2026-05-07 > 适用范围:UMS (User Management System) --- ## 1. 技术栈与框架选型 ### 1.1 后端技术栈 | 层级 | 技术选型 | 版本/说明 | |------|---------|----------| | **开发语言** | Go | 1.21+,高性能、原生并发、低内存占用 | | **Web 框架** | Gin | 轻量级、高性能 HTTP 路由与中间件 | | **ORM / 数据库** | GORM | 支持 PostgreSQL / SQLite / MySQL,自动迁移 | | **缓存** | Redis (go-redis) | 可选启用,分布式会话与热点缓存 | | **本地缓存** | 自研 LocalCache | 内存 L1 缓存,TTL + 后台清理 | | **配置管理** | Viper | YAML + 环境变量统一配置 | | **日志** | Zap | 高性能结构化日志 | | **JWT** | golang-jwt/jwt | RS256 签名,支持 JTI 与 Token 滚动轮换 | | **密码哈希** | golang.org/x/crypto/argon2 | Argon2id,启动时自适应校准 | | **TOTP 2FA** | github.com/pquerna/otp | RFC 6238 兼容 | | **监控** | Prometheus + OpenTelemetry | 指标采集与链路追踪 | | **限流** | Uber Rate Limit / 自研 | 令牌桶 + 内存清理 | | **容器化** | Docker | 单容器 + Docker Compose 编排 | | **编排(可选)** | Kubernetes | 生产集群部署 | ### 1.2 前端技术栈(Admin 后台) | 层级 | 技术选型 | 说明 | |------|---------|------| | **框架** | React 18 + TypeScript | 类型安全、组件化开发 | | **构建工具** | Vite | 快速冷启动与热更新 | | **UI 组件库** | Ant Design 5 | 企业级后台组件 | | **状态管理** | React Context(会话态) | 不引入重型状态库 | | **HTTP 客户端** | 原生 `fetch` + 统一请求客户端 | 无 Axios 依赖 | | **路由** | React Router 6 | 受保护路由方案 | | **样式** | CSS Modules + CSS Variables + AntD Theme Token | 无 styled-components | ### 1.3 基础设施 | 组件 | 技术选型 | 说明 | |------|---------|------| | **负载均衡** | Nginx | 反向代理、SSL 终止、静态资源缓存 | | **消息队列(可选)** | Kafka / RabbitMQ | 异步事件、Webhook 投递 | | **对象存储(可选)** | OSS / S3 | 头像与文件上传 | | **监控大盘** | Grafana | 可视化 Prometheus 指标 | | **日志收集** | ELK / Loki | 集中化日志检索 | --- ## 2. 目录结构与分层说明 项目采用 **Clean Architecture** 分层,依赖方向始终向内: ``` handler → service → repository → domain ``` ### 2.1 目录结构 ``` ├── cmd/ │ ├── server/ # HTTP 服务入口 │ └── ums/ # CLI 工具入口 ├── internal/ │ ├── api/ │ │ ├── handler/ # HTTP 请求处理器 (Handler 层) │ │ ├── middleware/ # Gin 中间件(认证、限流、日志、CORS 等) │ │ └── router/ # 路由注册与分组 │ ├── auth/ │ │ └── providers/ # OAuth2 Provider 实现 │ ├── cache/ # 本地缓存 + Redis 封装 │ ├── concurrent/ # 并发工具(WorkerPool、SingleFlight) │ ├── config/ # 配置结构与加载 │ ├── database/ # GORM 初始化、连接池、读写分离 │ ├── domain/ # 领域实体(User、Role、Permission 等) │ ├── e2e/ # 端到端测试 │ ├── integration/ # 集成测试 │ ├── middleware/ # 共享中间件(与 api/middleware 区分) │ ├── monitoring/ # Prometheus 指标与链路追踪 │ ├── pagination/ # 游标分页与 OFFSET 分页封装 │ ├── performance/ # 性能测试与基准测试 │ ├── pkg/ # 内部公共包 │ │ ├── errors/ # 错误码与错误包装 │ │ ├── ip/ # IP 解析与过滤 │ │ ├── oauth/ # OAuth2 辅助工具 │ │ └── ... │ ├── repository/ # 数据访问层(Repository 层) │ ├── robustness/ # 鲁棒性工具(熔断、重试) │ ├── security/ # 安全工具(密码策略、加密、校验) │ ├── server/ # HTTP Server 生命周期管理 │ ├── service/ # 业务逻辑层(Service 层) │ ├── testdb/ # 测试数据库辅助 │ ├── testutil/ # 测试工具函数 │ └── util/ # 通用工具包 ├── pkg/ │ └── errors/ # 对外暴露的错误包 ├── configs/ │ └── config.yaml # 默认配置文件 ├── deployments/ │ ├── docker-compose.yml # 本地编排 │ └── kubernetes/ # K8s 清单 ├── docs/ # 设计文档与 API 文档 ├── frontend/ # React Admin 前端(独立目录) ├── migrations/ # 数据库迁移脚本 ├── scripts/ # 构建与运维脚本 ├── sdk/ # 客户端 SDK ├── uploads/ # 本地上传文件存储(受保护) └── tools/ # 开发工具 ``` ### 2.2 分层职责 | 分层 | 目录 | 职责 | 依赖规则 | |------|------|------|----------| | **Handler 层** | `internal/api/handler` | HTTP 请求解析、参数校验、响应封装、调用 Service | 仅依赖 Service 层 | | **Service 层** | `internal/service` | 业务逻辑编排、事务管理、领域事件触发 | 仅依赖 Repository 与 Domain | | **Repository 层** | `internal/repository` | 数据持久化、查询优化、ORM 操作 | 仅依赖 Domain | | **Domain 层** | `internal/domain` | 实体定义、值对象、领域规则、接口契约 | 不依赖任何外部层 | | **基础设施层** | `internal/cache`, `internal/database`, `internal/config` | 技术实现(缓存、数据库、配置) | 可被上层通过接口注入 | --- ## 3. 核心模块架构图 ### 3.1 整体模块交互 ``` ┌─────────────────────────────────────────────────────────────────────┐ │ 外部客户端 │ │ (Web Admin / Mobile App / 第三方 OAuth / SDK 调用方) │ └───────────────────────────────┬─────────────────────────────────────┘ │ ┌───────────────────────────────▼─────────────────────────────────────┐ │ API 网关层 │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ 认证中间件 │ │ 限流中间件 │ │ 日志中间件 │ │ │ │ (JWT/OAuth2) │ │ (RateLimit) │ │ (AccessLog) │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ CORS 中间件 │ │ CSRF 中间件 │ │ IP 过滤中间件 │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ └───────────────────────────────┬─────────────────────────────────────┘ │ ┌───────────────────────────────▼─────────────────────────────────────┐ │ Handler 层 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Auth │ │ User │ │ Role │ │ Device │ │ Log │ │ │ │ Handler │ │ Handler │ │ Handler │ │ Handler │ │ Handler │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Admin │ │ Webhook │ │ 2FA │ │ OAuth │ │ │ │ Handler │ │ Handler │ │ Handler │ │ Handler │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ └───────────────────────────────┬─────────────────────────────────────┘ │ ┌───────────────────────────────▼─────────────────────────────────────┐ │ Service 层 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Auth │ │ User │ │ Role │ │ Device │ │ Log │ │ │ │ Service │ │ Service │ │ Service │ │ Service │ │ Service │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Admin │ │ Webhook │ │ 2FA │ │ OAuth │ │ │ │ Service │ │ Service │ │ Service │ │ Service │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ └───────────────────────────────┬─────────────────────────────────────┘ │ ┌───────────────────────────────▼─────────────────────────────────────┐ │ Repository 层 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ UserRepo │ │ RoleRepo │ │ PermRepo │ │ DevRepo │ │ LogRepo │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Social │ │ Password │ │ Webhook │ │ │ │ Repo │ │ History │ │ Repo │ │ │ └──────────┘ └──────────┘ └──────────┘ │ └───────────────────────────────┬─────────────────────────────────────┘ │ ┌───────────────────────────────▼─────────────────────────────────────┐ │ Domain 层 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ User │ │ Role │ │ Permission│ │ Device │ │ LoginLog │ │ │ │ Entity │ │ Entity │ │ Entity │ │ Entity │ │ Entity │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Operation│ │ Webhook │ │ Password │ │ │ │ Log │ │ Entity │ │ History │ │ │ │ Entity │ │ │ │ Entity │ │ │ └──────────┘ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────────────────────────┘ ``` ### 3.2 请求处理流程 | 步骤 | 组件 | 动作 | |------|------|------| | 1 | Nginx / Ingress | SSL 终止、静态资源缓存、反向代理 | | 2 | Gin Router | 路由匹配、路径参数解析 | | 3 | Middleware Chain | 限流 → IP 过滤 → CORS → CSRF → 认证 → 日志 | | 4 | Handler | 绑定请求体、参数校验、调用 Service | | 5 | Service | 业务逻辑、权限检查、事务封装 | | 6 | Repository | ORM 查询 / 写入、缓存读写 | | 7 | Database / Cache | 数据持久化或缓存命中 | | 8 | Service | 组装领域结果、触发异步事件(Webhook、日志) | | 9 | Handler | 统一响应封装(code / message / data) | | 10 | Middleware | 记录访问日志、更新 Prometheus 指标 | ### 3.3 核心模块职责表 | 模块 | 职责 | 关键文件/包 | |------|------|------------| | **认证 (Auth)** | 注册、登录、登出、JWT 签发与刷新、密码重置、TOTP | `internal/auth`, `internal/api/handler/auth_handler.go` | | **用户 (User)** | CRUD、头像上传、状态管理、角色分配、导入导出 | `internal/service/user_service.go`, `internal/repository/user_repository.go` | | **RBAC** | 角色管理、权限管理、角色继承、权限树 | `internal/domain/role.go`, `internal/service/role_service.go` | | **设备 (Device)** | 设备注册、信任管理、多设备登出 | `internal/api/handler/device_handler.go` | | **日志 (Log)** | 登录日志、操作日志、查询与审计 | `internal/repository/log_repository.go` | | **OAuth2** | 第三方登录、社交账号绑定/解绑 | `internal/auth/providers/` | | **Webhook** | 事件订阅、异步投递、重试机制 | `internal/service/webhook_service.go` | | **Admin** | 仪表盘统计、批量导入导出 | `internal/api/handler/admin_handler.go` | | **安全 (Security)** | 密码策略、IP 过滤、敏感数据脱敏 | `internal/security/` | --- ## 4. 数据模型 ### 4.1 实体关系总览 ``` users ||--o{ user_roles : "多对多" users ||--o{ devices : "一对多" users ||--o{ login_logs : "一对多" users ||--o{ operation_logs : "一对多" users ||--o{ user_social_accounts : "一对多" users ||--o{ password_history : "一对多" roles ||--o{ user_roles : "多对多" roles ||--o{ role_permissions : "多对多" roles ||--o{ roles : "自关联(继承)" permissions ||--o{ role_permissions : "多对多" webhooks ||--o{ webhook_deliveries : "一对多" ``` ### 4.2 核心实体定义 #### User(用户) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGINT | PK, AutoIncrement | 用户唯一标识 | | username | VARCHAR(50) | UNIQUE, Index | 用户名 | | email | VARCHAR(100) | UNIQUE, Index | 邮箱地址 | | phone | VARCHAR(20) | UNIQUE, Index | 手机号 | | password | VARCHAR(255) | Not Null | Argon2id 哈希密码 | | nickname | VARCHAR(50) | Nullable | 昵称 | | avatar | VARCHAR(255) | Nullable | 头像 URL | | gender | TINYINT | Default 0 | 性别:0-未知,1-男,2-女 | | birthday | DATE | Nullable | 生日 | | region | VARCHAR(50) | Nullable | 所在地区 | | bio | VARCHAR(500) | Nullable | 个性签名 | | status | TINYINT | Default 1, Index | 状态:0-待激活,1-正常,2-锁定,3-禁用 | | totp_secret | VARCHAR(255) | Nullable | TOTP 密钥(加密存储) | | totp_enabled | TINYINT | Default 0 | 是否启用 TOTP | | password_changed_at | DATETIME | Nullable | 密码最后修改时间(用于 Token 失效) | | last_login_time | DATETIME | Nullable | 最后登录时间 | | last_login_ip | VARCHAR(50) | Nullable | 最后登录 IP | | created_at | DATETIME | Default CURRENT_TIMESTAMP | 创建时间 | | updated_at | DATETIME | AutoUpdate | 更新时间 | | deleted_at | DATETIME | Nullable, Index | 软删除时间(GORM 支持) | **索引**:`uk_username`, `uk_email`, `uk_phone`, `idx_status`, `idx_created_at` #### Role(角色) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGINT | PK, AutoIncrement | 角色唯一标识 | | name | VARCHAR(50) | UNIQUE, Not Null | 角色名称 | | code | VARCHAR(50) | UNIQUE, Not Null | 角色代码(如 `admin`, `user`) | | description | VARCHAR(200) | Nullable | 角色描述 | | parent_id | BIGINT | FK → roles.id, Nullable | 父角色 ID(继承关系) | | level | INT | Default 1, Index | 角色层级 | | is_system | TINYINT | Default 0 | 是否系统内置角色 | | is_default | TINYINT | Default 0, Index | 是否新用户默认角色 | | status | TINYINT | Default 1 | 状态:0-禁用,1-启用 | | created_at | DATETIME | Default CURRENT_TIMESTAMP | 创建时间 | | updated_at | DATETIME | AutoUpdate | 更新时间 | **索引**:`uk_name`, `uk_code`, `idx_parent_id`, `idx_level` **初始数据**: - `id=1, code='admin', name='管理员', is_system=1` —— 系统管理员 - `id=2, code='user', name='普通用户', is_system=1, is_default=1` —— 默认用户 #### Permission(权限) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGINT | PK, AutoIncrement | 权限唯一标识 | | name | VARCHAR(50) | Not Null | 权限名称 | | code | VARCHAR(100) | UNIQUE, Not Null | 权限代码(格式 `resource:action`) | | resource | VARCHAR(50) | Not Null, Index | 资源名称(如 `user`, `role`) | | action | VARCHAR(20) | Not Null | 操作类型:`read` / `write` / `delete` / `execute` | | description | VARCHAR(200) | Nullable | 权限描述 | | type | VARCHAR(20) | Not Null, Index | 权限类型:`api` / `page` / `button` | | group_id | BIGINT | Nullable, Index | 权限分组 ID | | status | TINYINT | Default 1 | 状态:0-禁用,1-启用 | | created_at | DATETIME | Default CURRENT_TIMESTAMP | 创建时间 | | updated_at | DATETIME | AutoUpdate | 更新时间 | **索引**:`uk_code`, `idx_resource`, `idx_group_id` #### Device(设备) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGINT | PK, AutoIncrement | 设备唯一标识 | | user_id | BIGINT | FK → users.id, Not Null, Index | 所属用户 | | device_id | VARCHAR(100) | UNIQUE, Not Null | 设备唯一标识字符串 | | device_name | VARCHAR(50) | Nullable | 设备名称 | | device_type | VARCHAR(20) | Not Null | 设备类型:`pc` / `mobile` / `tablet` | | os | VARCHAR(50) | Nullable | 操作系统 | | browser | VARCHAR(50) | Nullable | 浏览器 | | ip | VARCHAR(50) | Nullable | 最近 IP | | location | VARCHAR(100) | Nullable | 地理位置 | | is_trusted | TINYINT | Default 0 | 是否信任设备(跳过 2FA) | | trust_expires_at | DATETIME | Nullable | 信任状态过期时间 | | last_active_time | DATETIME | Nullable, Index | 最后活跃时间 | | created_at | DATETIME | Default CURRENT_TIMESTAMP | 创建时间 | **索引**:`idx_user_id`, `uk_device_id`, `idx_last_active_time` #### LoginLog(登录日志) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGINT | PK, AutoIncrement | 日志唯一标识 | | user_id | BIGINT | FK → users.id, Nullable, Index | 用户 ID(匿名登录为 NULL) | | login_type | VARCHAR(20) | Not Null | 登录方式:`password` / `code` / `wechat` / `github` / ... | | login_method | VARCHAR(20) | Nullable | 认证子方式 | | ip | VARCHAR(50) | Nullable, Index | 登录 IP | | location | VARCHAR(100) | Nullable | 地理位置 | | device_id | VARCHAR(100) | Nullable | 设备标识 | | user_agent | VARCHAR(500) | Nullable | User-Agent | | status | TINYINT | Not Null, Index | 状态:0-失败,1-成功 | | failure_reason | VARCHAR(200) | Nullable | 失败原因 | | created_at | DATETIME | Default CURRENT_TIMESTAMP, Index | 登录时间 | **索引**:`idx_user_id`, `idx_ip`, `idx_status`, `idx_created_at` **分区建议**(MySQL/PostgreSQL):按月分区,保留最近 12 个月。 #### OperationLog(操作日志) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGINT | PK, AutoIncrement | 日志唯一标识 | | user_id | BIGINT | FK → users.id, Nullable, Index | 操作人 ID | | action_type | VARCHAR(50) | Not Null | 操作类型(如 `user:create`) | | resource_type | VARCHAR(50) | Not Null, Index | 资源类型(如 `user`, `role`) | | resource_id | BIGINT | Nullable | 资源 ID | | action | VARCHAR(20) | Not Null | 动作:`create` / `update` / `delete` | | old_value | TEXT | Nullable | 操作前值(JSON) | | new_value | TEXT | Nullable | 操作后值(JSON) | | ip | VARCHAR(50) | Nullable | 操作 IP | | user_agent | VARCHAR(500) | Nullable | User-Agent | | created_at | DATETIME | Default CURRENT_TIMESTAMP, Index | 操作时间 | **索引**:`idx_user_id`, `idx_resource_type`, `idx_created_at` **分区建议**(MySQL/PostgreSQL):按月分区,保留最近 24 个月。 ### 4.3 关联表 | 关联表 | 关联实体 | 说明 | |--------|---------|------| | `user_roles` | users ↔ roles | 多对多:用户角色分配 | | `role_permissions` | roles ↔ permissions | 多对多:角色权限分配 | | `user_social_accounts` | users | 一对多:第三方社交账号绑定 | | `password_history` | users | 一对多:密码历史(防重用) | | `webhooks` | - | Webhook 配置 | | `webhook_deliveries` | webhooks | Webhook 投递日志 | --- ## 5. 接口设计(RESTful API 分组列表) 基础路径:`/api/v1` 认证方式:`Authorization: Bearer ` 统一响应:`{ "code": 0, "message": "success", "data": {} }` ### 5.1 认证组(Auth) | 方法 | 路径 | 认证 | 说明 | |------|------|------|------| | POST | `/auth/register` | 公开 | 用户注册 | | POST | `/auth/bootstrap-admin` | 公开 | 初始化管理员(首次启动) | | POST | `/auth/login` | 公开 | 账号密码登录 | | POST | `/auth/login/email-code` | 公开 | 邮箱验证码登录 | | POST | `/auth/login/code` | 公开 | 短信验证码登录 | | POST | `/auth/refresh` | 公开 | 刷新 Access Token(Refresh Token) | | POST | `/auth/logout` | 需认证 | 登出 | | GET | `/auth/userinfo` | 需认证 | 获取当前用户信息 | | GET | `/auth/capabilities` | 公开 | 获取系统能力配置 | | GET | `/auth/activate` | 公开 | 邮箱激活 | | POST | `/auth/resend-activation` | 公开 | 重发激活邮件 | | POST | `/auth/forgot-password` | 公开 | 忘记密码 | | GET | `/auth/reset-password` | 公开 | 验证重置 Token 页面 | | POST | `/auth/reset-password` | 公开 | 提交新密码 | | POST | `/auth/send-email-code` | 公开 | 发送邮箱验证码 | | POST | `/auth/send-code` | 公开 | 发送短信验证码 | | GET | `/auth/csrf-token` | 公开 | 获取 CSRF Token | | GET | `/auth/captcha` | 公开 | 获取验证码配置 | | GET | `/auth/captcha/image` | 公开 | 获取图形验证码 | | POST | `/auth/captcha/verify` | 公开 | 验证图形验证码 | ### 5.2 双因素认证组(2FA / TOTP) | 方法 | 路径 | 认证 | 说明 | |------|------|------|------| | GET | `/auth/2fa/status` | 需认证 | 获取 2FA 状态 | | GET | `/auth/2fa/setup` | 需认证 | 获取 TOTP 设置信息(QR Code) | | POST | `/auth/2fa/enable` | 需认证 | 启用 TOTP | | POST | `/auth/2fa/disable` | 需认证 | 禁用 TOTP | | POST | `/auth/2fa/verify` | 需认证 | 验证 TOTP 码 | ### 5.3 OAuth2 组 | 方法 | 路径 | 认证 | 说明 | |------|------|------|------| | GET | `/auth/oauth/providers` | 公开 | 获取已配置的 Provider 列表 | | GET | `/auth/oauth/:provider` | 公开 | 跳转 OAuth2 授权页 | | GET | `/auth/oauth/:provider/callback` | 公开 | OAuth2 回调处理 | ### 5.4 用户组(User) | 方法 | 路径 | 认证/权限 | 说明 | |------|------|----------|------| | GET | `/users` | 管理员 | 用户列表(分页、筛选、排序) | | GET | `/users/:id` | 本人或管理员 | 获取用户详情 | | PUT | `/users/:id` | 本人或管理员 | 更新用户信息 | | DELETE | `/users/:id` | `user:delete` | 删除用户 | | PUT | `/users/:id/password` | 本人 | 修改密码 | | PUT | `/users/:id/status` | `user:manage` | 修改用户状态 | | GET | `/users/:id/roles` | 本人或管理员 | 获取用户角色 | | PUT | `/users/:id/roles` | `user:manage` | 分配用户角色 | | POST | `/users/:id/avatar` | 需认证 | 上传头像 | | GET | `/users/me/social-accounts` | 需认证 | 获取当前用户社交账号 | | POST | `/users/me/bind-social` | 需认证 | 绑定社交账号 | | DELETE | `/users/me/bind-social/:provider` | 需认证 | 解绑社交账号 | ### 5.5 角色与权限组(RBAC) | 方法 | 路径 | 认证/权限 | 说明 | |------|------|----------|------| | POST | `/roles` | 管理员 | 创建角色 | | GET | `/roles` | 管理员 | 角色列表 | | GET | `/roles/:id` | 管理员 | 角色详情 | | PUT | `/roles/:id` | 管理员 | 更新角色 | | DELETE | `/roles/:id` | 管理员 | 删除角色 | | PUT | `/roles/:id/status` | 管理员 | 修改角色状态 | | GET | `/roles/:id/permissions` | 管理员 | 获取角色权限 | | PUT | `/roles/:id/permissions` | 管理员 | 分配角色权限 | | POST | `/permissions` | 管理员 | 创建权限 | | GET | `/permissions` | 管理员 | 权限列表 | | GET | `/permissions/tree` | 管理员 | 权限树形结构 | | GET | `/permissions/:id` | 管理员 | 权限详情 | | PUT | `/permissions/:id` | 管理员 | 更新权限 | | DELETE | `/permissions/:id` | 管理员 | 删除权限 | | PUT | `/permissions/:id/status` | 管理员 | 修改权限状态 | ### 5.6 设备组(Device) | 方法 | 路径 | 认证 | 说明 | |------|------|------|------| | GET | `/devices` | 需认证 | 设备列表 | | POST | `/devices` | 需认证 | 注册设备 | | GET | `/devices/:id` | 需认证 | 设备详情 | | PUT | `/devices/:id` | 需认证 | 更新设备 | | DELETE | `/devices/:id` | 需认证 | 删除设备 | | PUT | `/devices/:id/status` | 需认证 | 修改设备状态 | | POST | `/devices/:id/trust` | 需认证 | 设置设备信任 | | DELETE | `/devices/:id/trust` | 需认证 | 取消设备信任 | | POST | `/devices/by-device-id/:deviceId/trust` | 需认证 | 按设备标识设置信任 | | GET | `/devices/me/trusted` | 需认证 | 获取信任设备列表 | | POST | `/devices/me/logout-others` | 需认证 | 登出所有其他设备 | | GET | `/devices/users/:id` | 管理员 | 获取指定用户的设备 | ### 5.7 日志组(Log) | 方法 | 路径 | 认证/权限 | 说明 | |------|------|----------|------| | GET | `/logs/login/me` | 需认证 | 当前用户登录日志 | | GET | `/logs/operation/me` | 需认证 | 当前用户操作日志 | | GET | `/logs/login` | 管理员 | 全量登录日志 | | GET | `/logs/operation` | 管理员 | 全量操作日志 | ### 5.8 Webhook 组 | 方法 | 路径 | 认证 | 说明 | |------|------|------|------| | POST | `/webhooks` | 需认证 | 创建 Webhook | | GET | `/webhooks` | 需认证 | Webhook 列表 | | PUT | `/webhooks/:id` | 需认证 | 更新 Webhook | | DELETE | `/webhooks/:id` | 需认证 | 删除 Webhook | | GET | `/webhooks/:id/deliveries` | 需认证 | 投递记录 | ### 5.9 管理员扩展组(Admin) | 方法 | 路径 | 认证/权限 | 说明 | |------|------|----------|------| | GET | `/admin/users/export` | 管理员 | 导出用户(CSV/XLSX) | | POST | `/admin/users/import` | 管理员 | 导入用户 | | GET | `/admin/users/import/template` | 管理员 | 下载导入模板 | | GET | `/admin/stats/dashboard` | 管理员 | 仪表盘统计 | | GET | `/admin/stats/users` | 管理员 | 用户统计 | ### 5.10 基础设施端点 | 方法 | 路径 | 认证 | 说明 | |------|------|------|------| | GET | `/health` | 公开 | 健康检查 | | GET | `/health/live` | 公开 | Liveness Probe | | GET | `/health/ready` | 公开 | Readiness Probe | | GET | `/metrics` | 公开 | Prometheus 指标 | | GET | `/swagger/*any` | 公开 | Swagger 文档 | --- ## 6. 安全设计 ### 6.1 认证机制 | 机制 | 实现 | 说明 | |------|------|------| | **JWT 访问令牌** | RS256 非对称签名 | Access Token 有效期短(默认 2h),携带用户 ID、角色、权限 | | **Refresh Token** | 独立令牌,滚动轮换 | 每次刷新后旧 Refresh Token 失效,防重放 | | **JTI 唯一标识** | timestamp(8B hex) + random(16B hex) | 防 Token 枚举,支持精确吊销 | | **Token 黑名单** | Redis / 内存缓存 | 登出、密码修改后 Token 立即失效 | | **密码修改失效(PCE)** | `password_changed_at` 字段 | 密码修改后旧 Token 自动失效 | | **TOTP 双因素认证** | RFC 6238 | 6 位动态码,支持信任设备跳过 | | **设备信任** | `is_trusted` + `trust_expires_at` | 信任设备在有效期内免 2FA | | **OAuth2 第三方登录** | 标准 Authorization Code 流程 | 支持 GitHub、Google、微信等 Provider | | **SSO 就绪** | JWT + 统一用户中心架构 | 可通过扩展支持单点登录 | ### 6.2 授权机制(RBAC) | 机制 | 实现 | 说明 | |------|------|------| | **角色继承** | 自关联 `parent_id` + 层级 `level` | 子角色自动继承父角色权限,最大深度 20 | | **权限代码** | `resource:action` 格式 | 如 `user:read`, `user:delete` | | **权限类型** | `api` / `page` / `button` | 覆盖接口、页面、按钮三级权限 | | **中间件鉴权** | `RequirePermission` / `RequireRole` | Handler 层统一拦截 | | **数据级鉴权** | Service 层用户 ID 比对 | 如用户只能修改自己的资料 | ### 6.3 限流与防护 | 机制 | 实现 | 说明 | |------|------|------| | **接口限流** | 令牌桶算法 | 按 IP / 用户维度限流,防止暴力破解 | | **限流内存清理** | 后台定期清理过期桶 | 防止内存泄漏 | | **登录失败锁定** | 递增延迟 + 最大重试次数 | 防暴力破解 | | **图形验证码** | 算术/字符验证码 | 注册、登录、重置密码前验证 | | **CSRF 防护** | Double Submit Cookie + Token | POST/PUT/DELETE/PATCH 自动校验 | | **CORS 白名单** | 配置化允许域名 | 拒绝危险通配符配置 | | **IP 过滤** | 黑白名单机制 | 支持按 IP 段拦截 | | **上传保护** | `/uploads` 路由认证中间件 | 防止未授权访问用户文件 | ### 6.4 密码策略 | 策略 | 实现 | 说明 | |------|------|------| | **哈希算法** | Argon2id | 内存硬函数,抗 GPU/ASIC 破解 | | **自适应校准** | `auth.CalibrateArgon2id` | 启动时根据 CPU 自动调整参数 | | **默认参数** | 64MB 内存,3 次迭代,4 并行度 | 平衡安全性与性能 | | **密码历史** | `password_history` 表 | 禁止重用最近 N 次密码 | | **历史异步保存** | goroutine + `context.WithTimeout` | 不阻塞主登录流程 | | **常数时间比较** | `subtle.ConstantTimeCompare` | 防时序攻击 | | **弱密码检测** | 常见弱密码字典 | 注册/修改时拦截 | ### 6.5 敏感数据保护 | 数据类型 | 保护措施 | |---------|---------| | **密码** | Argon2id 哈希,不可逆 | | **TOTP Secret** | AES-256-GCM 加密存储 | | **手机号/邮箱** | 日志中部分脱敏(如 `138****1234`) | | **Token** | 仅存储 JTI,不存储完整 Token | | **备份数据** | 加密存储,异地备份 | | **传输层** | TLS 1.2+,HSTS 头部 | ### 6.6 已修复安全漏洞(关键) | 问题 | 严重等级 | 修复要点 | |------|----------|----------| | LIKE 查询 SQL 注入 | P0 | 参数化查询 + 转义 | | 登录计数竞态条件 | P0 | 原子操作 / 分布式锁 | | Refresh Token 黑名单 fail-open | P0 | 默认拒绝策略 | | 验证码 Replay 攻击 | P0 | 一次性使用 + 过期校验 | | CORS 危险配置 | P0 | 白名单校验 | | UpdateUser IDOR 越权 | P0 | 数据级权限校验 | | Login TOTP 绕过 | P0 | 验证流程强制化 | | 游标分页数据错乱 | P0 | 稳定排序键 | --- ## 7. 性能优化清单 ### 7.1 数据库优化 | 优化项 | 状态 | 说明 | |--------|------|------| | 批量查询替代循环查询(`FilterExistingUsernames`) | **[已实施]** | `generateUniqueUsername` 使用批量 IN 查询替代逐条循环 | | 单一查询替代串行查询(`FindByAccount`) | **[已实施]** | `findUserForLogin` 使用一次查询覆盖 username/email/phone | | 角色继承深度限制(`maxAncestorDepth=20`) | **[已实施]** | 防止递归查询栈溢出与性能退化 | | 数据库索引优化 | 已实施 | `users` 表 uk_username/uk_email/uk_phone/idx_status;`login_logs` 按时间分区 | | 预加载关联数据(GORM Preload) | 已实施 | 用户列表预加载角色,避免 N+1 | | 游标分页替代 OFFSET | 已实施 | 大数据量列表使用 ID 游标分页 | | 连接池调优 | 已实施 | `max_open_conns=100`, `max_idle_conns=20`, 连接生命周期 30min | | 数据库读写分离 | 待实施 | 主库写、从库读,轮询负载均衡 | ### 7.2 缓存优化 | 优化项 | 状态 | 说明 | |--------|------|------| | L1 本地缓存 | 已实施 | 内存缓存用户、权限、Token 黑名单,TTL 5min | | L2 Redis 缓存 | 可选 | 分布式缓存,TTL 30min,支持集群 | | 缓存穿透防护 | 已实施 | 空值缓存 + 布隆过滤器 | | 缓存击穿防护 | 已实施 | SingleFlight 互斥锁,热点 Key 只回源一次 | | 缓存雪崩防护 | 已实施 | 随机 TTL 抖动,避免集中过期 | ### 7.3 计算与并发优化 | 优化项 | 状态 | 说明 | |--------|------|------| | Argon2id 启动时自适应校准 | **[已实施]** | 根据当前 CPU 能力自动选择最优参数 | | 密码历史异步保存 | **[已实施]** | goroutine + `context.WithTimeout` 不阻塞登录主流程 | | RateLimiter 定期清理 | **[已实施]** | 后台定时清理过期限流桶,防止内存泄漏 | | WorkerPool 协程池 | 已实施 | 批量操作限制并发度,防止 goroutine 爆炸 | | 异步事件处理 | 已实施 | Webhook 投递、日志写入异步化 | ### 7.4 接口与路由优化 | 优化项 | 状态 | 说明 | |--------|------|------| | `/uploads` 路由认证保护 | **[已实施]** | 静态文件路由增加认证中间件 | | Gzip 压缩 | 已实施 | 响应体 > 1KB 自动压缩 | | HTTP/2 支持 | 已实施 | Nginx / Go 1.21+ 原生支持 | | 静态资源 CDN | 待实施 | 生产环境头像、JS/CSS 走 CDN | | 请求体大小限制 | 已实施 | 防止大文件 DOS | ### 7.5 性能目标 | 指标 | 目标值 | 说明 | |------|--------|------| | 并发用户数 | 100,000 | 集群部署 + Redis 会话 | | QPS | 100,000 | 多级缓存 + 读写分离 | | P50 响应时间 | < 100ms | 缓存命中场景 | | P99 响应时间 | < 500ms | 含数据库回源 | | 缓存命中率 | > 95% | L1 + L2 综合 | --- ## 8. 部署架构建议 ### 8.1 单机部署(SQLite + 可选 Redis) 适用场景:开发测试、小型团队、单机低并发。 ``` ┌─────────────────────────────────────────┐ │ Nginx (反向代理) │ │ SSL 终止 / 静态资源缓存 │ └──────────────────┬──────────────────────┘ │ ┌──────────────────▼──────────────────────┐ │ UMS 应用服务 (Go/Gin) │ │ ┌─────────────────────────────────┐ │ │ │ Handler / Service / Repository │ │ │ │ L1 本地缓存 (内存) │ │ │ └─────────────────────────────────┘ │ │ │ │ │ ┌────────────────┼────────────────┐ │ │ ▼ ▼ ▼ │ │ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ SQLite │ │ Redis │ │ uploads│ │ │ │ (主存) │ │(可选L2)│ │ (受保护)│ │ │ └────────┘ └────────┘ └────────┘ │ └─────────────────────────────────────────┘ ``` **配置要点**: - SQLite 文件存储在持久化卷 - 每日全量备份 SQLite 文件 - Redis 可选,用于分布式锁和二级缓存 - 单实例无状态,重启不影响数据 ### 8.2 集群部署(PostgreSQL + Redis Cluster) 适用场景:生产环境、中大型应用、高可用要求。 ``` ┌─────────────────────────────────────────────────────────────┐ │ 全局负载均衡 (GSLB) │ │ DNS 轮询 / 健康检查 / 故障转移 │ └──────────────────────┬──────────────────────────────────────┘ │ ┌──────────────┼──────────────┐ │ │ │ ┌───────▼──────┐ ┌────▼──────┐ ┌─────▼──────┐ │ 机房 A │ │ 机房 B │ │ 机房 C │ │ (北京) │ │ (上海) │ │ (灾备) │ │ │ │ │ │ │ │ ┌──────────┐ │ │ ┌────────┐│ │ ┌────────┐ │ │ │ Nginx │ │ │ │ Nginx ││ │ │ Nginx │ │ │ │ 负载均衡 │ │ │ │负载均衡││ │ │负载均衡│ │ │ └────┬─────┘ │ │ └───┬────┘│ │ └───┬────┘ │ │ │ │ │ │ │ │ │ │ │ ┌────▼─────┐ │ │ ┌───▼───┐ │ │ ┌───▼───┐ │ │ │ UMS 集群 │ │ │ │UMS 集群│ │ │ │UMS 集群│ │ │ │ (多实例) │ │ │ │(多实例)│ │ │ │(多实例)│ │ │ │ L1 缓存 │ │ │ │L1 缓存 │ │ │ │L1 缓存 │ │ │ └────┬─────┘ │ │ └───┬───┘ │ │ └───┬───┘ │ │ │ │ │ │ │ │ │ │ │ ┌────▼─────┐ │ │ ┌───▼───┐ │ │ ┌───▼───┐ │ │ │Redis 集群│ │ │ │Redis │ │ │ │Redis │ │ │ │ 哨兵模式 │ │ │ │哨兵 │ │ │ │哨兵 │ │ │ └────┬─────┘ │ │ └───┬───┘ │ │ └───┬───┘ │ │ │ │ │ │ │ │ │ │ │ ┌────▼─────┐ │ │ ┌───▼───┐ │ │ ┌───▼───┐ │ │ │PG 主从 │ │ │ │PG 主从│ │ │ │PG 主从│ │ │ │ 主(写) │ │ │ │ 主(写)│ │ │ │ 主(写)│ │ │ │ 从(读)×2 │ │ │ │从(读)×2│ │ │ │从(读)×2│ │ │ └──────────┘ │ │ └───────┘ │ │ └───────┘ │ └──────────────┘ └───────────┘ └────────────┘ ``` **配置要点**: - PostgreSQL 主从复制,从库承担读流量 - Redis 哨兵模式,高可用缓存与会话存储 - UMS 实例无状态,支持水平扩展 - Nginx 层做限流、SSL、静态缓存 - 跨机房异步复制,RPO < 1min ### 8.3 容器化部署(Docker Compose) ```yaml # docker-compose.yml 核心服务 services: ums: image: ums:latest ports: - "8080:8080" environment: - DATABASE_TYPE=postgres - DATABASE_DSN=postgresql://ums:pass@postgres:5432/ums - REDIS_ADDR=redis:6379 volumes: - ./uploads:/app/uploads depends_on: - postgres - redis deploy: replicas: 2 postgres: image: postgres:15-alpine volumes: - pgdata:/var/lib/postgresql/data redis: image: redis:7-alpine volumes: - redisdata:/data nginx: image: nginx:alpine ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/nginx.conf ``` ### 8.4 Kubernetes 部署 | 资源 | 类型 | 说明 | |------|------|------| | **Deployment** | `ums-api` | 3+ 副本,滚动更新 | | **Service** | `ClusterIP` + `LoadBalancer` | 内部集群 + 外部暴露 | | **ConfigMap** | `ums-config` | 应用配置外置 | | **Secret** | `ums-secrets` | JWT 私钥、数据库密码 | | **HPA** | 自动扩缩容 | CPU > 70% 或 QPS 阈值触发 | | **PVC** | `uploads-pvc` | 共享存储(或替换为 OSS) | | **Ingress** | Nginx Ingress | 路由、SSL、限流 | | **PodDisruptionBudget** | `minAvailable: 2` | 保证升级时可用性 | ### 8.5 监控与告警 | 层级 | 组件 | 采集指标 | |------|------|----------| | 基础设施 | Node Exporter | CPU、内存、磁盘、网络 | | 中间件 | Redis Exporter / Postgres Exporter | 连接数、QPS、慢查询 | | 应用 | Prometheus + OpenTelemetry | HTTP 延迟、错误率、缓存命中率 | | 日志 | Grafana Loki / ELK | 结构化日志检索 | | 告警 | Prometheus Alertmanager | P99 > 500ms、错误率 > 1%、磁盘 > 80% | --- ## 附录:文档索引 | 文档 | 路径 | 说明 | |------|------|------| | API 契约 | `docs/API.md` | 完整接口定义与响应示例 | | 数据模型 | `docs/DATA_MODEL.md` | 数据库表结构、索引、ER 图 | | 技术架构 | `docs/ARCHITECTURE.md` | 性能优化、缓存策略、监控 | | 部署指南 | `docs/DEPLOYMENT.md` | 环境配置、升级、回滚 | | 安全文档 | `docs/SECURITY.md` | 安全机制、漏洞修复记录 | | PRD | `docs/PRD.md` | 产品需求文档 | --- *本文档持续更新,如有变更请同步更新本文件及相关子文档。*