866 行
41 KiB
Markdown
866 行
41 KiB
Markdown
|
|
# TDD-07 反作弊与安全设计
|
|||
|
|
|
|||
|
|
> 文档类型:技术设计文档(Technical Design Document)
|
|||
|
|
> 版本:1.0
|
|||
|
|
> 日期:2026-07-02
|
|||
|
|
> 关联文档:TDD-04《数据库表结构设计》、TDD-05《API接口设计》、GDD-02《底层核心机制》、GDD-03《战斗系统设计》、GDD-06《经济系统设计》、GDD-13《佣兵大厅与悬赏系统》、GDD-14《稀有宝物流转与拍卖系统》
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. 文档信息
|
|||
|
|
|
|||
|
|
| 项目 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| 目标 | 为《洪荒大陆》挂机手游定义反作弊与安全设计规范,覆盖服务端权威模型、异常行为检测、经济安全、举报惩罚、接口安全与数据安全六大领域。 |
|
|||
|
|
| 读者 | 服务端开发、客户端开发、安全工程师、运维、QA |
|
|||
|
|
| 技术栈 | Nakama 3.x + Go 插件 + PostgreSQL 16 + Valkey + Nacos 2.x + Cocos Creator 3.x |
|
|||
|
|
| 核心约束 | 无任务系统、无赛季重置、概率/机遇驱动、文字战报、ATB 行动条、功法加持、能量体系(非体力) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 服务端权威模型
|
|||
|
|
|
|||
|
|
### 2.1 设计原则
|
|||
|
|
|
|||
|
|
本项目采用 **服务端权威(Server-Authoritative)** 架构:客户端仅负责展示与发起请求,所有涉及游戏状态变更的逻辑在服务端计算并持久化。客户端提交的数据仅作为"意图声明",不作为事实来源。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
客户端 服务端 数据库/缓存
|
|||
|
|
│ │ │
|
|||
|
|
│── 请求(意图) ────────►│ │
|
|||
|
|
│ │── 读取状态 ──────────►│
|
|||
|
|
│ │◄─ 返回当前状态 ───────│
|
|||
|
|
│ │ │
|
|||
|
|
│ │── 校验 + 计算 ────────►│
|
|||
|
|
│ │── 写入结果 ──────────►│
|
|||
|
|
│ │ │
|
|||
|
|
│◄─ 返回结算结果 ───────│ │
|
|||
|
|
│ │ │
|
|||
|
|
│── 仅做 UI 展示 ────────│ │
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.2 服务端必须校验的操作清单
|
|||
|
|
|
|||
|
|
以下操作必须由服务端完整计算,客户端不可参与任何判定逻辑:
|
|||
|
|
|
|||
|
|
| 操作类别 | 具体操作 | 校验要点 | 关联接口 |
|
|||
|
|
|----------|----------|----------|----------|
|
|||
|
|
| **战斗结算** | PVE 战斗(游历/副本/遗迹)、PVP 战斗、悬赏追杀 | 服务端加载双方属性快照 → ATB 引擎计算 → 生成战报 → 写入 `battles` + `battle_logs` | `POST /api/v1/combats`、`POST /api/v1/combats/pvp` |
|
|||
|
|
| **突破渡劫** | 小境界突破、大境界渡劫、破界晋级 | 服务端校验修为/材料/护法条件 → 概率判定 → 更新 `characters.realm_tier` / `minor_realm` / `world_tier` | `POST /api/v1/characters/{id}/realm/breakthrough`、`POST .../tribulation`、`POST .../world-break` |
|
|||
|
|
| **经济交易** | 货币增减、交易行挂单/购买、拍卖出价、悬赏赏金、天机阁情报 | 服务端校验余额 → 原子扣款/加款 → 写入 `economy_audit_logs` → 同步 Valkey 钱包缓存 | `POST /api/v1/market/orders/{id}/buy`、`POST /api/v1/auctions/{id}/bids` 等 |
|
|||
|
|
| **地图移动** | 跨区域移动、进入副本/遗迹、破界传送 | 服务端校验 `world_tier` / `realm_tier` 解锁状态 → 更新 `characters.world_tier` | `POST /api/v1/instances/{id}/enter` |
|
|||
|
|
| **技能学习** | 功法升层、技能学习、玉简拓印、加持切换 | 服务端校验种族/境界/属性/SAN/材料条件 → 概率判定 → 写入 `character_skills` / `character_manuals` | `POST /api/v1/characters/{id}/manuals/{mid}/upgrade`、`POST .../skills/learn` |
|
|||
|
|
| **弟子派遣** | 弟子代派任务、领地产出 | 服务端计算成功率/死亡率 → 异步结算 → 写入 `disciple_missions` | `POST /api/v1/disciples/{id}/dispatch` |
|
|||
|
|
| **组织操作** | 创建/加入/退出组织、领地竞标、帮派资金 | 服务端校验权限/条件 → 原子更新 `guilds` / `guild_members` / `guild_territories` | `POST /api/v1/guilds`、`POST .../territories/bids` |
|
|||
|
|
| **社交关系** | 道侣/结义/师徒请求、关系解除 | 服务端校验互斥关系/冷却时间 → 写入 `social_relations` / `lovers` / `sworn_brothers` | `POST /api/v1/relations/{type}/requests` |
|
|||
|
|
|
|||
|
|
### 2.3 客户端仅做展示与请求的原则
|
|||
|
|
|
|||
|
|
| 原则 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| **不信任客户端数值** | 客户端发送的属性值、伤害值、概率值全部忽略,服务端自行从数据库/缓存加载 |
|
|||
|
|
| **不信任客户端时间** | 所有时间判定以服务端 `timestamptz` 为准,客户端时间仅用于 UI 倒计时展示 |
|
|||
|
|
| **不信任客户端随机** | 概率判定(突破/渡劫/技能顿悟/掉落)全部使用服务端 CSPRNG(`crypto/rand`) |
|
|||
|
|
| **不信任客户端状态** | 客户端报告的"战斗胜利""突破成功"等状态无效,必须由服务端判定并返回 |
|
|||
|
|
| **客户端仅提交意图** | 客户端发送"我要对目标 X 使用技能 Y",服务端校验技能存在性/能量/CD/目标合法性后执行 |
|
|||
|
|
|
|||
|
|
### 2.4 客户端校验(可选,提升体验)
|
|||
|
|
|
|||
|
|
客户端可进行以下前置校验以减少无效请求,但服务端仍需独立校验:
|
|||
|
|
|
|||
|
|
- 当前能量是否足够(避免发送必定失败的请求)
|
|||
|
|
- 目标是否在交互范围内
|
|||
|
|
- 材料是否在背包中
|
|||
|
|
- 冷却是否结束
|
|||
|
|
|
|||
|
|
> **关键**:客户端校验失败仅阻止本地 UI 操作,不作为任何服务端逻辑的依据。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 异常行为检测
|
|||
|
|
|
|||
|
|
### 3.1 加速检测
|
|||
|
|
|
|||
|
|
#### 3.1.1 时间回拨检测
|
|||
|
|
|
|||
|
|
| 检测项 | 实现方式 | 阈值 | 响应 |
|
|||
|
|
|--------|----------|------|------|
|
|||
|
|
| 客户端时钟偏移 | 登录时客户端上报本地时间戳,服务端计算偏差 `abs(client_ts - server_ts)` | > 300 秒 | 记录日志,连续 3 次超阈值标记可疑 |
|
|||
|
|
| 请求时间序列单调性 | 同一 `character_id` 的请求 `X-Trace-Id` 中嵌入服务端接收时间戳,检查是否递增 | 出现回退 | 标记异常,回退的请求拒绝处理 |
|
|||
|
|
| 游戏内时间跳跃 | 对比两次请求的 `game_timestamp` 差值与现实间隔 | 游戏时间增量 > 现实间隔 × 3.5 | 触发告警,暂停游历/挂机产出 |
|
|||
|
|
|
|||
|
|
#### 3.1.2 速度异常检测
|
|||
|
|
|
|||
|
|
| 检测项 | 实现方式 | 阈值 | 响应 |
|
|||
|
|
|--------|----------|------|------|
|
|||
|
|
| 地图移动速度 | 计算两次位置变更的 `distance / time_elapsed` | > 角色最大移动速度 × 1.2 | 重置位置,标记异常 |
|
|||
|
|
| 请求频率 | 基于 Valkey 滑动窗口计数器 `rate:{character_id}:{path}` | 超过 TDD-05 §2.5 定义的限流值 | 返回 429,累计触发次数 |
|
|||
|
|
| 战斗间隔 | 检查两次战斗请求的时间间隔 | < 战斗最短耗时(ATB 最少回合数) | 拒绝请求,记录日志 |
|
|||
|
|
| 挂机产出速率 | 对比实际产出与理论产出 `expected = base_rate × duration × modifiers` | 实际 > 理论 × 1.3 | 截断超出部分,标记异常 |
|
|||
|
|
|
|||
|
|
#### 3.1.3 请求频率异常检测
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// Go 伪代码:滑动窗口限流器(基于 Valkey)
|
|||
|
|
func CheckRateLimit(characterID, path string, limit int, window time.Duration) bool {
|
|||
|
|
key := fmt.Sprintf("rate:%s:%s", characterID, path)
|
|||
|
|
now := time.Now().UnixMilli()
|
|||
|
|
windowStart := now - window.Milliseconds()
|
|||
|
|
|
|||
|
|
pipe := valkey.Pipeline()
|
|||
|
|
pipe.ZRemRangeByScore(ctx, key, "0", fmt.Sprintf("%d", windowStart))
|
|||
|
|
pipe.ZAdd(ctx, key, &valkey.Z{Score: float64(now), Member: uuid.New().String()})
|
|||
|
|
pipe.ZCard(ctx, key)
|
|||
|
|
pipe.Expire(ctx, key, window)
|
|||
|
|
results := pipe.Exec(ctx)
|
|||
|
|
|
|||
|
|
count := results[2].(*valkey.IntCmd).Val()
|
|||
|
|
return count <= int64(limit)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.2 数据篡改检测
|
|||
|
|
|
|||
|
|
#### 3.2.1 属性/货币/背包哈希校验
|
|||
|
|
|
|||
|
|
对客户端展示的关键数据附加校验哈希,服务端在关键节点验证一致性:
|
|||
|
|
|
|||
|
|
| 数据域 | 校验方式 | 触发时机 |
|
|||
|
|
|--------|----------|----------|
|
|||
|
|
| 角色属性快照 | `HMAC-SHA256(character_id + base_stats_json + battle_stats_json + secret_salt)` | 登录同步、战斗前加载 |
|
|||
|
|
| 货币余额 | `HMAC-SHA256(character_id + currency_code + amount + secret_salt)` | 每次货币变更后生成,客户端下次请求携带 |
|
|||
|
|
| 背包物品 | `HMAC-SHA256(character_id + item_count_hash + secret_salt)` | 物品变更后生成 |
|
|||
|
|
|
|||
|
|
> **注意**:哈希校验仅用于客户端篡改检测,服务端始终以数据库数据为准。校验失败不直接封号,而是标记可疑并触发人工审核。
|
|||
|
|
|
|||
|
|
#### 3.2.2 服务端内部一致性校验
|
|||
|
|
|
|||
|
|
| 校验项 | 实现方式 | 频率 |
|
|||
|
|
|--------|----------|------|
|
|||
|
|
| 货币守恒 | `currency_balances.amount = total_earned - total_spent`(从 `economy_audit_logs` 聚合) | 每日凌晨批处理 |
|
|||
|
|
| 背包守恒 | `inventories` 中的物品数量变化应与 `economy_audit_logs` 中的物品流转记录一致 | 每日凌晨批处理 |
|
|||
|
|
| 境界一致性 | `characters.realm_tier` 应与 `character_realms.is_current=true` 的记录一致 | 实时校验(突破/渡劫时) |
|
|||
|
|
| 装备合法性 | `equipments` 引用的 `inventory_id` 应属于同一 `character_id`,且 `bind_type` 与穿戴状态一致 | 装备变更时 |
|
|||
|
|
|
|||
|
|
### 3.3 机器人挂机检测
|
|||
|
|
|
|||
|
|
#### 3.3.1 行为模式分析
|
|||
|
|
|
|||
|
|
| 特征 | 正常玩家 | 疑似机器人 | 检测方式 |
|
|||
|
|
|------|----------|------------|----------|
|
|||
|
|
| 操作间隔分布 | 随机波动,有高峰低谷 | 高度规律,近似固定间隔 | 统计操作间隔的标准差(σ < 阈值则可疑) |
|
|||
|
|
| 活跃时长 | 有休息,单次 1~3 小时 | 24 小时不间断 | 检查连续在线时长 |
|
|||
|
|
| 决策模式 | 有犹豫、有选择 | 固定路线、固定操作序列 | 序列熵分析(操作序列熵低于阈值则可疑) |
|
|||
|
|
| 响应速度 | 对事件有合理反应时间 | 对随机事件瞬间响应 | 事件推送 → 响应延迟统计 |
|
|||
|
|
| 设备指纹 | 正常设备特征 | 模拟器/多开特征 | 设备指纹库比对(见 §3.4.4) |
|
|||
|
|
|
|||
|
|
#### 3.3.2 验证码策略
|
|||
|
|
|
|||
|
|
| 触发条件 | 验证码类型 | 说明 |
|
|||
|
|
|----------|------------|------|
|
|||
|
|
| 连续在线 > 8 小时 | 图形验证码 / 滑块 | 强制验证,失败则暂停游历产出 |
|
|||
|
|
| 操作间隔标准差低于阈值 | 行为验证码(点选/拖拽) | 3 次失败标记为可疑 |
|
|||
|
|
| 被举报 2 次以上(24 小时内) | 图形验证码 | 每次登录强制验证,持续 3 天 |
|
|||
|
|
| 异常 IP 段批量注册 | 注册时强制验证码 | 结合设备指纹去重 |
|
|||
|
|
|
|||
|
|
#### 3.3.3 机器学习辅助检测(长期规划)
|
|||
|
|
|
|||
|
|
| 阶段 | 内容 |
|
|||
|
|
|------|------|
|
|||
|
|
| 数据采集 | 采集正常玩家行为序列:操作间隔、路径选择、战斗决策、市场行为 |
|
|||
|
|
| 特征工程 | 提取操作熵、时间分布特征、社交图谱密度、经济行为模式 |
|
|||
|
|
| 模型训练 | 使用 Isolation Forest 或 LSTM-AutoEncoder 训练异常检测模型 |
|
|||
|
|
| 线上部署 | 对可疑行为打分,超过阈值触发人工审核,不自动封号 |
|
|||
|
|
|
|||
|
|
### 3.4 协议攻击检测
|
|||
|
|
|
|||
|
|
#### 3.4.1 重放攻击防护
|
|||
|
|
|
|||
|
|
| 机制 | 实现 |
|
|||
|
|
|------|------|
|
|||
|
|
| **Nonce 校验** | 每个请求携带 `X-Nonce: <uuid>`,服务端在 Valkey 中存储已用 Nonce(TTL 5 分钟),重复 Nonce 拒绝处理 |
|
|||
|
|
| **Timestamp 校验** | 请求携带 `X-Timestamp: <unix_ms>`,服务端校验 `abs(now - timestamp) < 60s`,超出窗口拒绝 |
|
|||
|
|
| **Sequence Number** | 高敏感操作(交易/拍卖/悬赏)使用递增 `X-Sequence`,服务端校验单调递增,跳跃过大拒绝 |
|
|||
|
|
| **Idempotency-Key** | 所有扣费/扣材料操作要求 `Idempotency-Key`,服务端以 `character_id + key` 去重 24 小时(TDD-05 §5) |
|
|||
|
|
|
|||
|
|
```protobuf
|
|||
|
|
// 请求头扩展(protobuf 定义)
|
|||
|
|
message SecureRequestHeader {
|
|||
|
|
string session_token = 1;
|
|||
|
|
string nonce = 2; // UUID v4
|
|||
|
|
int64 timestamp = 3; // Unix 毫秒
|
|||
|
|
int64 sequence = 4; // 单调递增序号
|
|||
|
|
string idempotency_key = 5; // 幂等键(写操作必填)
|
|||
|
|
bytes signature = 6; // HMAC-SHA256 签名(高敏感操作)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.4.2 中间人攻击防护
|
|||
|
|
|
|||
|
|
| 措施 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| 全链路 TLS 1.3 | HTTPS / WSS / gRPC 全部启用 TLS 1.3,禁止降级到 TLS 1.2 以下 |
|
|||
|
|
| 证书固定(Certificate Pinning) | 客户端内置服务端证书指纹,防止中间人伪造证书 |
|
|||
|
|
| 请求签名 | 高敏感操作(交易/出价/悬赏)要求客户端对请求体做 HMAC-SHA256 签名,密钥由 Nakama session 派生(TDD-05 §5) |
|
|||
|
|
| 响应签名 | 服务端对关键响应(战斗结算/突破结果/交易确认)附加签名,客户端验证完整性 |
|
|||
|
|
|
|||
|
|
#### 3.4.3 伪造 Token 防护
|
|||
|
|
|
|||
|
|
| 机制 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| Nakama Session 签名 | Token 由 Nakama 使用 HMAC-SHA256 签名,服务端校验签名完整性 |
|
|||
|
|
| Token 绑定 | Token 与 `device_id` + `ip_geo` 绑定,异地登录触发二次验证 |
|
|||
|
|
| Token 吊销 | 异常行为检测到后,通过 Nakama Admin API 强制吊销 Token |
|
|||
|
|
| Token 刷新 | 长期 Token(60 天)可被服务端主动过期,强制重新登录 |
|
|||
|
|
|
|||
|
|
#### 3.4.4 设备指纹与多开检测
|
|||
|
|
|
|||
|
|
| 特征 | 采集方式 | 用途 |
|
|||
|
|
|------|----------|------|
|
|||
|
|
| `device_id` | 客户端生成并上报 | 账号绑定,防止刷号 |
|
|||
|
|
| 设备型号 / OS 版本 | 客户端上报 | 模拟器检测 |
|
|||
|
|
| 屏幕分辨率 / DPI | 客户端上报 | 多开检测(同一分辨率批量注册) |
|
|||
|
|
| IP 地址 / 地理位置 | 服务端获取 | 异地登录检测、IP 黑名单 |
|
|||
|
|
| 安装应用列表哈希 | 客户端采集(需用户授权) | 外挂工具检测 |
|
|||
|
|
|
|||
|
|
> **隐私合规**:设备指纹采集需符合《个人信息保护法》,在隐私政策中明确告知,并提供关闭选项(关闭后功能受限)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 经济安全
|
|||
|
|
|
|||
|
|
### 4.1 RMT(Real Money Trading)检测
|
|||
|
|
|
|||
|
|
#### 4.1.1 异常交易模式检测
|
|||
|
|
|
|||
|
|
| 检测规则 | 触发条件 | 响应 |
|
|||
|
|
|----------|----------|------|
|
|||
|
|
| **单向大额转账** | 24 小时内 A → B 的交易行购买总额 > 5000 灵石,且 B → A 无反向交易 | 标记可疑,冻结双方交易功能 24 小时,触发人工审核 |
|
|||
|
|
| **新号转金** | 创建 < 7 天的角色在交易行购买总额 > 2000 灵石 | 标记可疑,限制交易行购买额度 |
|
|||
|
|
| **关联账号网络** | 多个账号之间形成闭环交易链(A→B→C→A) | 标记整组账号,触发人工审核 |
|
|||
|
|
| **固定价格交易** | 同一卖家对同一买家以相同价格反复交易 | 标记可疑,检查是否为 RMT 通道 |
|
|||
|
|
| **离线交易** | 卖家长时间不在线但持续有高价成交 | 标记可疑,检查是否为傀儡账号 |
|
|||
|
|
|
|||
|
|
#### 4.1.2 RMT 检测评分模型
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
RMT_RISK_SCORE = (
|
|||
|
|
单向交易金额占比 × 0.3 +
|
|||
|
|
交易频率异常度 × 0.2 +
|
|||
|
|
账号年龄因子 × 0.15 +
|
|||
|
|
社交图谱稀疏度 × 0.15 +
|
|||
|
|
价格偏离度 × 0.2
|
|||
|
|
) × 100
|
|||
|
|
|
|||
|
|
阈值:
|
|||
|
|
score < 40 → 正常
|
|||
|
|
40 ≤ score < 70 → 标记观察
|
|||
|
|
70 ≤ score < 90 → 标记可疑,限制交易
|
|||
|
|
score ≥ 90 → 标记高危,冻结账号,触发人工审核
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.1.3 RMT 数据库表
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- RMT 检测记录表
|
|||
|
|
CREATE TABLE rmt_detection_records (
|
|||
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
character_id uuid NOT NULL REFERENCES characters(id),
|
|||
|
|
risk_score numeric(5,2) NOT NULL,
|
|||
|
|
risk_level varchar(16) NOT NULL, -- normal / watch / suspicious / critical
|
|||
|
|
trigger_rules jsonb NOT NULL, -- 触发的规则列表
|
|||
|
|
related_ids uuid[], -- 关联的交易/订单 ID
|
|||
|
|
status varchar(16) NOT NULL DEFAULT 'pending', -- pending / reviewing / confirmed / cleared
|
|||
|
|
reviewer_id uuid, -- 审核人
|
|||
|
|
review_note text,
|
|||
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|||
|
|
reviewed_at timestamptz
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_rmt_character ON rmt_detection_records(character_id, created_at);
|
|||
|
|
CREATE INDEX idx_rmt_status ON rmt_detection_records(status, risk_level);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.2 刷金检测
|
|||
|
|
|
|||
|
|
#### 4.2.1 产出速率异常检测
|
|||
|
|
|
|||
|
|
| 检测维度 | 基线计算 | 异常阈值 | 响应 |
|
|||
|
|
|----------|----------|----------|------|
|
|||
|
|
| 游历产出 | `base_rate × duration × race_modifier × realm_modifier` | 实际 > 基线 × 1.5 | 截断超出部分,标记异常 |
|
|||
|
|
| 副本产出 | `instance_reward × difficulty_coefficient × party_bonus` | 实际 > 预期 × 1.3 | 截断,标记异常 |
|
|||
|
|
| 挂机产出 | `gathering_rate × duration × talent_modifier` | 实际 > 理论 × 1.5 | 截断,标记异常 |
|
|||
|
|
| 悬赏收益 | `bounty_reward × completion_rate` | 单日悬赏收益 > 基线 × 3 | 标记异常,限制接取 |
|
|||
|
|
|
|||
|
|
#### 4.2.2 多号联动检测
|
|||
|
|
|
|||
|
|
| 检测规则 | 触发条件 | 响应 |
|
|||
|
|
|----------|----------|------|
|
|||
|
|
| 同 IP 批量注册 | 同一 IP 24 小时内注册 > 3 个账号 | 注册时强制验证码,标记关联 |
|
|||
|
|
| 同设备多号 | 同一 `device_id` 绑定 > 2 个账号 | 标记关联,共享风控评分 |
|
|||
|
|
| 多号向单号集中转金 | > 3 个账号在 24 小时内向同一账号交易 | 标记目标账号,触发人工审核 |
|
|||
|
|
| 多号协同刷副本 | 同一 IP 段的多个账号同时进入同一副本 | 标记异常,检查是否为工作室 |
|
|||
|
|
|
|||
|
|
#### 4.2.3 产出监控看板指标
|
|||
|
|
|
|||
|
|
| 指标 | 计算方式 | 告警阈值 |
|
|||
|
|
|------|----------|----------|
|
|||
|
|
| 全服货币通胀率 | `(total_supply_today - total_supply_yesterday) / total_supply_yesterday` | > 5%/天 |
|
|||
|
|
| 人均产出偏差 | `avg(player产出) / theoretical_avg` | > 1.5 |
|
|||
|
|
| Top 1% 产出占比 | `top1%_产出 / total_产出` | > 30% |
|
|||
|
|
| 新号产出集中度 | `accounts_7d产出 / total_产出` | > 20% |
|
|||
|
|
|
|||
|
|
### 4.3 洗钱检测
|
|||
|
|
|
|||
|
|
#### 4.3.1 交易行价格操纵检测
|
|||
|
|
|
|||
|
|
| 检测规则 | 触发条件 | 响应 |
|
|||
|
|
|----------|----------|------|
|
|||
|
|
| **异常低价挂单** | 挂单价格 < 近 7 天同物品均价 × 0.3 | 标记可疑,限制成交,触发人工审核 |
|
|||
|
|
| **异常高价购买** | 购买价格 > 近 7 天同物品均价 × 3.0 | 标记可疑,记录买家信息 |
|
|||
|
|
| **自买自卖** | 卖家与买家为同一账号(或关联账号) | 拒绝成交,标记异常 |
|
|||
|
|
| **批量低买高卖** | 短时间内大量低价收购后高价出售 | 标记可疑,检查是否为价格操纵 |
|
|||
|
|
| **价格异常波动** | 物品价格在 1 小时内波动 > 50% | 触发告警,人工审核 |
|
|||
|
|
|
|||
|
|
#### 4.3.2 拍卖自拍自买检测
|
|||
|
|
|
|||
|
|
| 检测规则 | 触发条件 | 响应 |
|
|||
|
|
|----------|----------|------|
|
|||
|
|
| 卖家 = 出价者 | `auctions.seller_id = auction_bids.bidder_id` | 数据库约束拒绝 |
|
|||
|
|
| 关联账号出价 | 卖家与出价者为关联账号(同设备/IP/交易历史) | 标记可疑,取消出价 |
|
|||
|
|
| 保证金循环 | 拍卖失败后保证金退回 → 立即用于下一次出价 | 检查资金循环频率 |
|
|||
|
|
| 价格虚高 | 拍卖成交价 > 近 7 天同物品均价 × 5.0 | 标记可疑,触发人工审核 |
|
|||
|
|
|
|||
|
|
#### 4.3.3 经济异常自动响应
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 经济异常响应状态机
|
|||
|
|
type EcoAnomalyResponse struct {
|
|||
|
|
Level string // watch / restrict / freeze / ban
|
|||
|
|
Actions []string
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var anomalyResponses = map[string]EcoAnomalyResponse{
|
|||
|
|
"watch": {
|
|||
|
|
Level: "watch",
|
|||
|
|
Actions: []string{"log_detail", "increase_monitoring"},
|
|||
|
|
},
|
|||
|
|
"restrict": {
|
|||
|
|
Level: "restrict",
|
|||
|
|
Actions: []string{"limit_trade_amount", "limit_trade_frequency", "require_captcha"},
|
|||
|
|
},
|
|||
|
|
"freeze": {
|
|||
|
|
Level: "freeze",
|
|||
|
|
Actions: []string{"freeze_trade", "freeze_withdraw", "notify_reviewer"},
|
|||
|
|
},
|
|||
|
|
"ban": {
|
|||
|
|
Level: "ban",
|
|||
|
|
Actions: []string{"freeze_account", "notify_admin", "create_ticket"},
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 举报与惩罚系统
|
|||
|
|
|
|||
|
|
### 5.1 举报类型
|
|||
|
|
|
|||
|
|
| 举报类型 | 说明 | 证据要求 | 优先级 |
|
|||
|
|
|----------|------|----------|--------|
|
|||
|
|
| **外挂/加速器** | 使用第三方工具加速/修改游戏 | 截图/视频 + 异常行为记录 | 高 |
|
|||
|
|
| **辱骂/骚扰** | 聊天频道发布不当言论 | 聊天记录截图 | 中 |
|
|||
|
|
| **诈骗** | 虚假交易/冒充GM/诱导转账 | 交易记录 + 聊天记录 | 高 |
|
|||
|
|
| **RMT** | 现金交易游戏资源 | 交易异常记录 | 高 |
|
|||
|
|
| **利用BUG** | 利用游戏漏洞获取不当利益 | 详细复现步骤 | 紧急 |
|
|||
|
|
| **其他** | 不当角色名/组织名等 | 截图 | 低 |
|
|||
|
|
|
|||
|
|
### 5.2 举报接口
|
|||
|
|
|
|||
|
|
| 项目 | 内容 |
|
|||
|
|
|------|------|
|
|||
|
|
| 功能 | 玩家提交举报 |
|
|||
|
|
| REST | `POST /api/v1/reports` |
|
|||
|
|
| 请求参数 | `target_character_id`(uuid)、`report_type`(string)、`description`(string)、`evidence_urls`([]string,可选)、`battle_id`(uuid,可选) |
|
|||
|
|
| 限流 | 5 次/天/角色 |
|
|||
|
|
| 错误码 | 9101(举报类型非法)、9102(目标不存在)、9103(今日举报次数已满)、9104(不可举报自己) |
|
|||
|
|
|
|||
|
|
### 5.3 举报数据表
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE player_reports (
|
|||
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
reporter_id uuid NOT NULL REFERENCES characters(id),
|
|||
|
|
target_id uuid NOT NULL REFERENCES characters(id),
|
|||
|
|
report_type varchar(32) NOT NULL, -- cheat / insult / fraud / rmt / bug_exploit / other
|
|||
|
|
description text,
|
|||
|
|
evidence_urls text[],
|
|||
|
|
related_battle_id uuid,
|
|||
|
|
related_trade_id uuid,
|
|||
|
|
status varchar(16) NOT NULL DEFAULT 'pending', -- pending / reviewing / resolved / dismissed
|
|||
|
|
priority smallint NOT NULL DEFAULT 2, -- 1=紧急 2=高 3=中 4=低
|
|||
|
|
reviewer_id uuid,
|
|||
|
|
review_result varchar(16), -- confirmed / insufficient_evidence / false_report
|
|||
|
|
review_note text,
|
|||
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|||
|
|
reviewed_at timestamptz
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_reports_status ON player_reports(status, priority, created_at);
|
|||
|
|
CREATE INDEX idx_reports_target ON player_reports(target_id, created_at);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.4 人工审核流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
玩家举报
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
自动分类 + 优先级排序
|
|||
|
|
│
|
|||
|
|
├── 紧急(利用BUG/RMT高危)──► 自动冻结可疑账号 ──► 24小时内人工审核
|
|||
|
|
│
|
|||
|
|
├── 高(外挂/诈骗)──► 48小时内人工审核
|
|||
|
|
│
|
|||
|
|
├── 中(辱骂)──► 72小时内人工审核
|
|||
|
|
│
|
|||
|
|
└── 低(其他)──► 7天内人工审核
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
人工审核
|
|||
|
|
│
|
|||
|
|
├── 确认违规 ──► 执行惩罚 ──► 通知举报者
|
|||
|
|
│
|
|||
|
|
├── 证据不足 ──► 标记观察 ──► 通知举报者
|
|||
|
|
│
|
|||
|
|
└── 误报 ──► 驳回 ──► 恶意举报者扣信用分
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.5 惩罚梯度
|
|||
|
|
|
|||
|
|
| 惩罚等级 | 适用场景 | 执行方式 | 持续时间 |
|
|||
|
|
|----------|----------|----------|----------|
|
|||
|
|
| **警告** | 首次轻微违规(辱骂/不当名) | 站内信通知 | 永久记录 |
|
|||
|
|
| **禁言** | 重复辱骂/刷屏 | 冻结聊天功能 | 1~7 天 |
|
|||
|
|
| **交易限制** | 疑似 RMT/刷金 | 限制交易行/拍卖操作 | 3~30 天 |
|
|||
|
|
| **功能封禁** | 使用外挂/严重 BUG 利用 | 封禁特定功能(PVP/副本/交易) | 7~90 天 |
|
|||
|
|
| **临时封号** | 严重违规/屡教不改 | 冻结账号,禁止登录 | 7~180 天 |
|
|||
|
|
| **永久封禁** | 极端违规(大规模 RMT/外挂开发/恶意攻击) | 永久冻结账号 + 设备黑名单 | 永久 |
|
|||
|
|
|
|||
|
|
#### 惩罚数据库表
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE punishment_records (
|
|||
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
character_id uuid NOT NULL REFERENCES characters(id),
|
|||
|
|
player_id uuid NOT NULL REFERENCES players(id),
|
|||
|
|
punishment_type varchar(16) NOT NULL, -- warning / mute / trade_ban / feature_ban / temp_ban / perm_ban
|
|||
|
|
reason text NOT NULL,
|
|||
|
|
report_id uuid REFERENCES player_reports(id),
|
|||
|
|
related_rule varchar(64), -- 违反的规则编号
|
|||
|
|
start_at timestamptz NOT NULL DEFAULT now(),
|
|||
|
|
end_at timestamptz, -- 永久封禁为 NULL
|
|||
|
|
is_active boolean NOT NULL DEFAULT true,
|
|||
|
|
issued_by varchar(32) NOT NULL, -- system / admin_id
|
|||
|
|
appeal_status varchar(16) DEFAULT 'none', -- none / pending / approved / rejected
|
|||
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_punishment_character ON punishment_records(character_id, is_active);
|
|||
|
|
CREATE INDEX idx_punishment_player ON punishment_records(player_id, is_active);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.6 申诉机制
|
|||
|
|
|
|||
|
|
| 项目 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| 申诉入口 | 游戏内「客服中心」→「申诉」 |
|
|||
|
|
| 申诉条件 | 被处罚后 7 天内可提交,每个处罚仅可申诉 1 次 |
|
|||
|
|
| 申诉内容 | 申诉理由(文字)+ 补充证据(截图/视频链接) |
|
|||
|
|
| 审核时限 | 3 个工作日内给出结果 |
|
|||
|
|
| 申诉结果 | 维持原判 / 减轻处罚 / 撤销处罚 |
|
|||
|
|
| 恶意申诉 | 连续 3 次申诉被驳回,后续申诉优先级降低 |
|
|||
|
|
|
|||
|
|
#### 申诉接口
|
|||
|
|
|
|||
|
|
| 项目 | 内容 |
|
|||
|
|
|------|------|
|
|||
|
|
| REST | `POST /api/v1/appeals` |
|
|||
|
|
| 请求参数 | `punishment_id`(uuid)、`reason`(string)、`evidence_urls`([]string) |
|
|||
|
|
| 限流 | 1 次/天 |
|
|||
|
|
| 错误码 | 9201(处罚不存在)、9202(已申诉过)、9203(申诉窗口已过) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. 接口安全
|
|||
|
|
|
|||
|
|
### 6.1 限流策略
|
|||
|
|
|
|||
|
|
限流在网关层(OpenResty/Traefik)基于 Token Bucket 实现,详见 TDD-05 §2.5。本节补充安全相关的限流细节。
|
|||
|
|
|
|||
|
|
#### 6.1.1 限流维度
|
|||
|
|
|
|||
|
|
| 维度 | 说明 | 实现 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| **IP 维度** | 防止单 IP 批量请求 | Valkey `SET rate:ip:{ip} {count} EX 60 NX` |
|
|||
|
|
| **账号维度** | 防止单账号刷接口 | Valkey `ZSET rate:char:{id}:{path}` 滑动窗口 |
|
|||
|
|
| **接口维度** | 热点接口单独限流 | 按 path + method 组合配置 |
|
|||
|
|
| **设备维度** | 防止多开刷量 | `device_id` 维度限流 |
|
|||
|
|
| **全局维度** | 防止 DDoS | 云防火墙 + WAF 全局限流 |
|
|||
|
|
|
|||
|
|
#### 6.1.2 安全增强限流
|
|||
|
|
|
|||
|
|
| 场景 | 策略 |
|
|||
|
|
|------|------|
|
|||
|
|
| 登录失败 | 5 次失败后锁定 15 分钟,10 次失败后锁定 1 小时 |
|
|||
|
|
| 注册 | 同 IP 每天最多 3 次注册 |
|
|||
|
|
| 交易操作 | 新账号(< 7 天)交易行操作限流加倍 |
|
|||
|
|
| 异常 IP | 被标记的 IP 段所有请求限流降至 1/10 |
|
|||
|
|
|
|||
|
|
### 6.2 防重放攻击
|
|||
|
|
|
|||
|
|
详见 §3.4.1。核心机制:
|
|||
|
|
|
|||
|
|
1. **Nonce + Timestamp**:每个请求携带唯一 Nonce 和时间戳,服务端校验唯一性与时效性
|
|||
|
|
2. **Sequence Number**:高敏感操作使用递增序号
|
|||
|
|
3. **Idempotency-Key**:所有写操作幂等控制
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 防重放校验中间件
|
|||
|
|
func AntiReplayMiddleware(next http.Handler) http.Handler {
|
|||
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|||
|
|
nonce := r.Header.Get("X-Nonce")
|
|||
|
|
timestamp := r.Header.Get("X-Timestamp")
|
|||
|
|
|
|||
|
|
// 1. 校验 Nonce 唯一性
|
|||
|
|
if !valkey.SetNX(ctx, "nonce:"+nonce, "1", 5*time.Minute).Val() {
|
|||
|
|
writeError(w, 9004, "duplicate request")
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 校验时间窗口
|
|||
|
|
ts, _ := strconv.ParseInt(timestamp, 10, 64)
|
|||
|
|
if abs(time.Now().UnixMilli()-ts) > 60000 {
|
|||
|
|
writeError(w, 9005, "request expired")
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
next.ServeHTTP(w, r)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.3 DDoS 防护
|
|||
|
|
|
|||
|
|
| 层级 | 措施 | 说明 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| **网络层** | 云防火墙 | 腾讯云 DDoS 防护,SYN Flood / UDP Flood / ACK Flood 清洗 |
|
|||
|
|
| **传输层** | CDN | 静态资源通过 CDN 分发,隐藏源站 IP |
|
|||
|
|
| **应用层** | WAF | OpenResty + lua-resty-waf,SQL 注入 / XSS / 路径遍历防护 |
|
|||
|
|
| **业务层** | 限流 + 验证码 | 超限请求返回 429,可疑流量触发验证码 |
|
|||
|
|
| **数据库层** | 连接池限制 | PostgreSQL `max_connections` 限制,防止连接耗尽 |
|
|||
|
|
|
|||
|
|
#### 6.3.1 WAF 规则
|
|||
|
|
|
|||
|
|
```nginx
|
|||
|
|
# OpenResty WAF 配置示例
|
|||
|
|
lua_shared_dict waf_rules 10m;
|
|||
|
|
|
|||
|
|
init_by_lua_block {
|
|||
|
|
local waf = require "resty.waf"
|
|||
|
|
waf.init()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
access_by_lua_block {
|
|||
|
|
local waf = require "resty.waf"
|
|||
|
|
local ctx = waf.new()
|
|||
|
|
ctx:set_option("mode", "ACTIVE")
|
|||
|
|
ctx:set_option("request_body_limit", 1048576) -- 1MB
|
|||
|
|
ctx:exec()
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.4 SQL 注入 / XSS 防护
|
|||
|
|
|
|||
|
|
| 防护项 | 措施 |
|
|||
|
|
|--------|------|
|
|||
|
|
| **SQL 注入** | 所有数据库操作使用参数化查询(`pgx` / `gorm` prepared statement),禁止字符串拼接 SQL |
|
|||
|
|
| **XSS** | 输出编码(HTML Entity / JSON Escape),CSP 头限制脚本来源 |
|
|||
|
|
| **CSRF** | API 使用 Token 认证(非 Cookie),天然免疫 CSRF |
|
|||
|
|
| **路径遍历** | 文件操作限制在白名单目录,禁止 `../` 路径 |
|
|||
|
|
| **命令注入** | 禁止 `os.Exec` 拼接用户输入,使用参数化调用 |
|
|||
|
|
| **SSRF** | 内部服务调用使用白名单 URL,禁止用户指定目标地址 |
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 参数化查询示例(pgx)
|
|||
|
|
func GetCharacter(db *pgxpool.Pool, characterID uuid.UUID) (*Character, error) {
|
|||
|
|
var c Character
|
|||
|
|
err := db.QueryRow(ctx,
|
|||
|
|
`SELECT id, name, race_id, world_tier, realm_tier, minor_realm
|
|||
|
|
FROM characters WHERE id = $1`, characterID,
|
|||
|
|
).Scan(&c.ID, &c.Name, &c.RaceID, &c.WorldTier, &c.RealmTier, &c.MinorRealm)
|
|||
|
|
return &c, err
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.5 CSP(Content Security Policy)头
|
|||
|
|
|
|||
|
|
```nginx
|
|||
|
|
add_header Content-Security-Policy "
|
|||
|
|
default-src 'self';
|
|||
|
|
script-src 'self' 'unsafe-inline' 'unsafe-eval';
|
|||
|
|
style-src 'self' 'unsafe-inline';
|
|||
|
|
img-src 'self' data: https:;
|
|||
|
|
connect-src 'self' wss://*.honghuang.example.com https://api.honghuang.example.com;
|
|||
|
|
font-src 'self';
|
|||
|
|
object-src 'none';
|
|||
|
|
base-uri 'self';
|
|||
|
|
form-action 'self';
|
|||
|
|
" always;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. 数据安全
|
|||
|
|
|
|||
|
|
### 7.1 敏感数据加密
|
|||
|
|
|
|||
|
|
| 数据类型 | 加密方式 | 存储位置 | 说明 |
|
|||
|
|
|----------|----------|----------|------|
|
|||
|
|
| 密码 | bcrypt(cost=12) | PostgreSQL `players` 表 | 仅账号系统使用,Nakama 内置处理 |
|
|||
|
|
| 支付信息 | AES-256-GCM | 独立支付数据库 | 充值记录加密存储,解密密钥独立管理 |
|
|||
|
|
| Session Token | HMAC-SHA256 签名 | Nakama 内部 | Token 本身不存储,仅存储签名 |
|
|||
|
|
| 设备指纹 | SHA-256 哈希 | PostgreSQL `players.device_id_hash` | 不存储原始设备 ID |
|
|||
|
|
| API 密钥 | 环境变量 / 密钥管理服务 | 服务端配置 | 不硬编码,不写入日志 |
|
|||
|
|
| 数据库连接 | TLS + 密钥文件 | 服务端配置 | PostgreSQL 连接使用 SSL |
|
|||
|
|
|
|||
|
|
### 7.2 日志脱敏
|
|||
|
|
|
|||
|
|
| 日志类型 | 脱敏规则 | 示例 |
|
|||
|
|
|----------|----------|------|
|
|||
|
|
| 玩家 IP | 保留前两段,后两段替换为 `***` | `192.168.***.***` |
|
|||
|
|
| 设备 ID | 仅保留哈希值 | `sha256:a1b2c3...` |
|
|||
|
|
| 角色名 | 正常记录(非敏感) | `铁爪传` |
|
|||
|
|
| 货币金额 | 正常记录(审计需要) | `1280` |
|
|||
|
|
| 请求体 | 移除 Token / 密码字段 | `{"device_id": "***", "platform": "ios"}` |
|
|||
|
|
| 错误堆栈 | 移除文件路径中的用户名 | `/app/internal/handler/...` |
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 日志脱敏中间件
|
|||
|
|
func SanitizeLogMiddleware(next http.Handler) http.Handler {
|
|||
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|||
|
|
// 脱敏请求头
|
|||
|
|
sanitizedHeaders := sanitizeHeaders(r.Header)
|
|||
|
|
|
|||
|
|
log.Info("incoming request",
|
|||
|
|
zap.String("method", r.Method),
|
|||
|
|
zap.String("path", r.URL.Path),
|
|||
|
|
zap.String("ip", maskIP(r.RemoteAddr)),
|
|||
|
|
zap.Any("headers", sanitizedHeaders),
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
next.ServeHTTP(w, r)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func maskIP(ip string) string {
|
|||
|
|
// "192.168.1.100:8080" -> "192.168.***.***:***"
|
|||
|
|
host, port, _ := net.SplitHostPort(ip)
|
|||
|
|
parts := strings.Split(host, ".")
|
|||
|
|
if len(parts) == 4 {
|
|||
|
|
return parts[0] + "." + parts[1] + ".***.***:***"
|
|||
|
|
}
|
|||
|
|
return "***"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.3 传输加密
|
|||
|
|
|
|||
|
|
| 场景 | 加密方式 | 说明 |
|
|||
|
|
|------|----------|------|
|
|||
|
|
| 客户端 ↔ 网关 | TLS 1.3 | HTTPS / WSS |
|
|||
|
|
| 网关 ↔ 服务端 | mTLS | 内部服务间双向 TLS |
|
|||
|
|
| 服务端 ↔ 数据库 | SSL | PostgreSQL `sslmode=verify-full` |
|
|||
|
|
| 服务端 ↔ Valkey | TLS | Valkey 6.0+ 支持 |
|
|||
|
|
| 服务端 ↔ Nacos | HTTPS | Nacos 2.x 配置传输 |
|
|||
|
|
|
|||
|
|
### 7.4 数据备份与恢复
|
|||
|
|
|
|||
|
|
| 备份类型 | 频率 | 保留策略 | 存储位置 |
|
|||
|
|
|----------|------|----------|----------|
|
|||
|
|
| PostgreSQL 全量备份 | 每日凌晨 03:00 | 保留 30 天 | 对象存储(腾讯云 COS) |
|
|||
|
|
| PostgreSQL WAL 增量 | 实时 | 保留 7 天 | 对象存储 |
|
|||
|
|
| Valkey RDB 快照 | 每 6 小时 | 保留 3 天 | 本地 + 对象存储 |
|
|||
|
|
| 配置备份 | 每次变更 | 永久 | Git 仓库 |
|
|||
|
|
|
|||
|
|
### 7.5 GDPR / 个人信息保护合规
|
|||
|
|
|
|||
|
|
#### 7.5.1 数据分类
|
|||
|
|
|
|||
|
|
| 数据类别 | 包含字段 | 处理依据 | 保留期限 |
|
|||
|
|
|----------|----------|----------|----------|
|
|||
|
|
| **账号信息** | player_id, device_id_hash, platform | 合同履行 | 账号存续期间 + 3 年 |
|
|||
|
|
| **游戏角色** | character_id, name, race_id, 等级/属性 | 合同履行 | 账号存续期间 |
|
|||
|
|
| **行为数据** | 登录日志, 操作日志, 战斗记录 | 合法利益(安全) | 12 个月 |
|
|||
|
|
| **交易数据** | 充值记录, 交易行记录 | 法律义务(财务) | 5 年 |
|
|||
|
|
| **设备信息** | 设备型号, OS 版本, IP | 合法利益(安全) | 6 个月 |
|
|||
|
|
| **聊天记录** | 聊天内容 | 合法利益(举报审核) | 3 个月 |
|
|||
|
|
|
|||
|
|
#### 7.5.2 用户权利实现
|
|||
|
|
|
|||
|
|
| 权利 | 实现方式 | 响应时限 |
|
|||
|
|
|------|----------|----------|
|
|||
|
|
| **知情权** | 隐私政策中明确告知数据收集范围与用途 | 首次安装时展示 |
|
|||
|
|
| **访问权** | 提供数据导出接口 `GET /api/v1/privacy/export` | 30 天内 |
|
|||
|
|
| **更正权** | 角色名修改、绑定手机修改 | 即时 |
|
|||
|
|
| **删除权** | 账号注销接口 `DELETE /api/v1/privacy/account` | 30 天内完成数据删除(法律保留除外) |
|
|||
|
|
| **撤回同意** | 关闭设备指纹采集(功能受限) | 即时 |
|
|||
|
|
| **可携带权** | 数据导出为 JSON/CSV 格式 | 30 天内 |
|
|||
|
|
|
|||
|
|
#### 7.5.3 账号注销流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
玩家申请注销
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
校验条件
|
|||
|
|
│
|
|||
|
|
├── 有未完成的交易/拍卖 ──► 拒绝,提示先处理
|
|||
|
|
│
|
|||
|
|
├── 有未结束的组织关系 ──► 拒绝,提示先退出
|
|||
|
|
│
|
|||
|
|
└── 条件满足 ──► 进入 30 天冷静期
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
30 天冷静期(可随时取消)
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
执行删除
|
|||
|
|
│
|
|||
|
|
├── 删除:characters, inventories, currency_balances, 等游戏数据
|
|||
|
|
│
|
|||
|
|
├── 匿名化:players 表保留 player_id 用于审计,其他字段替换为匿名值
|
|||
|
|
│
|
|||
|
|
└── 保留:economy_audit_logs, punishment_records(法律义务)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. 安全审计与监控
|
|||
|
|
|
|||
|
|
### 8.1 审计日志
|
|||
|
|
|
|||
|
|
| 日志类型 | 记录内容 | 保留期限 |
|
|||
|
|
|----------|----------|----------|
|
|||
|
|
| 登录日志 | player_id, ip, device_id_hash, login_time, login_result | 12 个月 |
|
|||
|
|
| 操作日志 | character_id, action, params_hash, result, timestamp | 12 个月 |
|
|||
|
|
| 经济日志 | economy_audit_logs(TDD-04 §5.4) | 12 个月 |
|
|||
|
|
| 安全日志 | 异常行为检测结果、封禁记录、举报处理记录 | 24 个月 |
|
|||
|
|
| 管理日志 | GM 操作、配置变更、手动封禁 | 永久 |
|
|||
|
|
|
|||
|
|
### 8.2 监控告警
|
|||
|
|
|
|||
|
|
| 监控项 | 告警阈值 | 通知方式 |
|
|||
|
|
|--------|----------|----------|
|
|||
|
|
| 登录失败率 | > 10%(5 分钟窗口) | 企业微信 + 邮件 |
|
|||
|
|
| 异常行为检测触发数 | > 50 次/小时 | 企业微信 |
|
|||
|
|
| 经济异常(通胀率) | > 5%/天 | 企业微信 + 邮件 |
|
|||
|
|
| API 错误率 | > 5%(1 分钟窗口) | 企业微信 + 电话 |
|
|||
|
|
| 数据库连接数 | > 80% max_connections | 企业微信 |
|
|||
|
|
| 内存使用率 | > 85% | 企业微信 |
|
|||
|
|
| 磁盘使用率 | > 90% | 企业微信 + 电话 |
|
|||
|
|
|
|||
|
|
### 8.3 安全事件响应流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
安全事件发生
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
自动检测 + 告警
|
|||
|
|
│
|
|||
|
|
├── P0(严重:数据泄露/服务中断)──► 15分钟内响应 ──► 1小时内止损 ──► 24小时内复盘
|
|||
|
|
│
|
|||
|
|
├── P1(高:大规模外挂/经济崩溃)──► 30分钟内响应 ──► 4小时内止损 ──► 3天内复盘
|
|||
|
|
│
|
|||
|
|
├── P2(中:个别外挂/RMT)──► 2小时内响应 ──► 24小时内处理
|
|||
|
|
│
|
|||
|
|
└── P3(低:轻微违规)──► 24小时内响应 ──► 7天内处理
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. 已确认决策记录表
|
|||
|
|
|
|||
|
|
| # | 决策 | 确认时间 |
|
|||
|
|
|---|------|----------|
|
|||
|
|
| ✅S01 | 所有战斗结算(PVE/PVP/悬赏/追杀)完全服务端权威,客户端仅提交意图 | 2026-07-02 |
|
|||
|
|
| ✅S02 | 突破/渡劫/破界的概率判定使用服务端 CSPRNG(`crypto/rand`),不使用客户端随机数 | 2026-07-02 |
|
|||
|
|
| ✅S03 | 经济交易(交易行/拍卖/悬赏/天机阁)全部服务端原子操作,写入 `economy_audit_logs` | 2026-07-02 |
|
|||
|
|
| ✅S04 | 地图移动/副本进入的服务端校验包含 `world_tier` / `realm_tier` / 解锁状态 / 钥匙/次数 | 2026-07-02 |
|
|||
|
|
| ✅S05 | 技能学习/功法升层的服务端校验包含种族/境界/属性/SAN/材料/来源标签 | 2026-07-02 |
|
|||
|
|
| ✅S06 | 防重放采用 Nonce + Timestamp + Sequence 三重机制,高敏感操作额外使用 Idempotency-Key | 2026-07-02 |
|
|||
|
|
| ✅S07 | 全链路 TLS 1.3,客户端证书固定(Certificate Pinning) | 2026-07-02 |
|
|||
|
|
| ✅S08 | RMT 检测采用评分模型,score ≥ 90 自动冻结账号并触发人工审核 | 2026-07-02 |
|
|||
|
|
| ✅S09 | 刷金检测基于产出速率基线对比 + 多号联动分析 | 2026-07-02 |
|
|||
|
|
| ✅S10 | 洗钱检测覆盖交易行价格操纵 + 拍卖自拍自买 + 价格异常波动 | 2026-07-02 |
|
|||
|
|
| ✅S11 | 举报系统支持 6 种类型,紧急举报自动冻结可疑账号,24 小时内人工审核 | 2026-07-02 |
|
|||
|
|
| ✅S12 | 惩罚梯度 6 级:警告/禁言/交易限制/功能封禁/临时封号/永久封禁 | 2026-07-02 |
|
|||
|
|
| ✅S13 | 申诉机制:处罚后 7 天内可申诉,每个处罚仅 1 次,3 个工作日出结果 | 2026-07-02 |
|
|||
|
|
| ✅S14 | 限流按 IP/账号/接口/设备/全局五维度,网关层 Token Bucket 实现 | 2026-07-02 |
|
|||
|
|
| ✅S15 | 日志脱敏:IP 保留前两段、设备 ID 仅存哈希、请求体移除 Token/密码 | 2026-07-02 |
|
|||
|
|
| ✅S16 | 账号注销 30 天冷静期,删除游戏数据,匿名化账号信息,保留法律义务数据 | 2026-07-02 |
|
|||
|
|
| ✅S17 | 敏感数据加密:密码 bcrypt、支付信息 AES-256-GCM、设备指纹 SHA-256 | 2026-07-02 |
|
|||
|
|
| ✅S18 | 安全事件分级响应:P0(15分钟)/P1(30分钟)/P2(2小时)/P3(24小时) | 2026-07-02 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 10. 验收标准
|
|||
|
|
|
|||
|
|
| # | 验收条目 | 测试方法 | 预期结果 |
|
|||
|
|
|---|----------|----------|----------|
|
|||
|
|
| 1 | 客户端伪造战斗胜利结果,服务端不接受 | 客户端篡改战斗结果字段发送请求 | 服务端独立计算,返回真实结果 |
|
|||
|
|
| 2 | 客户端伪造突破概率,服务端不接受 | 客户端发送 `success: true` 字段 | 服务端独立判定,返回真实结果 |
|
|||
|
|
| 3 | 客户端伪造货币余额,服务端不接受 | 客户端发送篡改后的余额哈希 | 服务端以数据库为准,哈希校验失败标记可疑 |
|
|||
|
|
| 4 | 重放攻击被拒绝 | 重复发送同一 Nonce 的请求 | 第二次返回 9004 |
|
|||
|
|
| 5 | 时间窗口外的请求被拒绝 | 发送 timestamp 偏差 > 60s 的请求 | 返回 9005 |
|
|||
|
|
| 6 | 高频请求触发限流 | 短时间发送超过限流阈值的请求 | 返回 429,响应头包含限流信息 |
|
|||
|
|
| 7 | 异常交易触发 RMT 检测 | 模拟单向大额转账行为 | 生成 rmt_detection_records,risk_level = suspicious |
|
|||
|
|
| 8 | 举报系统正常工作 | 提交举报并检查状态流转 | 举报创建成功,状态为 pending |
|
|||
|
|
| 9 | 惩罚系统正常执行 | 执行禁言惩罚 | 角色聊天功能被禁用,到期自动恢复 |
|
|||
|
|
| 10 | 申诉流程正常 | 对处罚提交申诉 | 申诉创建成功,状态为 pending |
|
|||
|
|
| 11 | SQL 注入防护 | 在请求参数中注入 SQL 语句 | 请求被拒绝或参数被安全处理 |
|
|||
|
|
| 12 | XSS 防护 | 在角色名/聊天内容中注入脚本 | 输出被编码,脚本不执行 |
|
|||
|
|
| 13 | TLS 证书固定生效 | 使用伪造证书连接 | 连接被拒绝 |
|
|||
|
|
| 14 | 日志脱敏正确 | 检查日志中的 IP 和设备 ID | IP 后两段为 `***`,设备 ID 为哈希值 |
|
|||
|
|
| 15 | 账号注销流程正确 | 申请注销并等待冷静期 | 30 天后游戏数据被删除,账号信息被匿名化 |
|
|||
|
|
| 16 | 经济守恒校验通过 | 运行每日批处理校验 | `currency_balances.amount = total_earned - total_spent` 成立 |
|
|||
|
|
| 17 | 机器人检测生效 | 模拟固定间隔操作模式 | 操作间隔标准差低于阈值时触发验证码 |
|
|||
|
|
| 18 | 设备指纹采集合规 | 检查隐私政策和采集逻辑 | 隐私政策明确告知,关闭选项可用 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 11. 与关联文档的映射
|
|||
|
|
|
|||
|
|
| 关联文档 | 本安全设计承接点 |
|
|||
|
|
|----------|------------------|
|
|||
|
|
| TDD-04 | `economy_audit_logs` 用于经济守恒校验;`rmt_detection_records` / `player_reports` / `punishment_records` 新增表 |
|
|||
|
|
| TDD-05 | 限流策略(§2.5)、认证方式(§2.2)、幂等控制(§5)在本文档扩展安全细节 |
|
|||
|
|
| GDD-02 | 战斗结算服务端权威(✅1);概率/机遇驱动(✅37);死亡惩罚(✅25);充值体系(✅22) |
|
|||
|
|
| GDD-03 | 战斗 ATB 引擎完全服务端计算;文字战报由服务端生成 |
|
|||
|
|
| GDD-06 | 经济 Faucet/Sink 框架;货币分层;交易行/拍卖/天机阁交易安全 |
|
|||
|
|
| GDD-13 | 佣兵委托/悬赏系统防刷检测 |
|
|||
|
|
| GDD-14 | 拍卖双轨制安全;追杀令防滥用;黑吃黑检测 |
|
|||
|
|
| GDD-16 | 社交关系防刷(道侣/结义/师徒请求频率限制) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 12. 版本记录
|
|||
|
|
|
|||
|
|
| 版本 | 日期 | 修订内容 | 作者 |
|
|||
|
|
|------|------|----------|------|
|
|||
|
|
| 1.0 | 2026-07-02 | 初始版本:服务端权威模型、异常行为检测(加速/篡改/机器人/协议攻击)、经济安全(RMT/刷金/洗钱)、举报惩罚系统、接口安全、数据安全、审计监控、验收标准 | Claude |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
*本文档阈值/参数均引用 Nacos 动态配置,服务端实现时以运行时配置为准,不硬编码。安全规则可根据运营数据持续调整。*
|