open-im-server/virgil_chat_server_design.md
2026-04-16 11:25:45 +08:00

676 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Virgil Security 接入到聊天系统设计方案(服务器)
## 1. 服务器设计目标
服务端的目标不是参与解密,而是提供 **业务承载层**
- 业务身份认证
- 设备管理
- Virgil JWT 签发
- 单聊/群聊会话管理
- 密文消息接入与路由
- 离线同步
- 文件上传/下载票据
- 群成员关系与群密钥版本索引
- 风控与设备吊销
---
## 2. 服务器总体架构
```mermaid
flowchart LR
subgraph Backend["业务服务端"]
B1["API Gateway"]
B2["Auth Service"]
B3["Virgil JWT Service"]
B4["Conversation Service"]
B5["Message Router / Sync"]
B6["Group Service"]
B7["Push Service"]
B8["File Ticket Service"]
B9["Risk / Device Service"]
B10["Metadata DB"]
end
subgraph Virgil["Virgil Cloud"]
V1["Cards / Public Key Directory"]
V2["Restore Related Services"]
end
subgraph OSS["Object Storage / CDN"]
O1["Encrypted File Objects"]
end
B1 --> B2
B1 --> B3
B1 --> B4
B1 --> B5
B1 --> B6
B1 --> B8
B1 --> B9
B2 --> B10
B3 --> B10
B4 --> B10
B5 --> B10
B6 --> B10
B8 --> O1
B9 --> B10
B3 --> V1
B3 --> V2
```
---
## 3. 服务器职责边界
## 3.1 服务端应该负责什么
- 用户登录与 token
- 设备注册与吊销
- Virgil JWT 签发
- 会话与群组元数据
- 密文消息存储
- 消息序列号与游标
- 离线消息投递
- 已读/已送达状态
- 文件票据
- 群成员变更事件
- 风控控制
## 3.2 服务端不应该负责什么
- 私钥保存
- 文本明文解析
- 文件明文解析
- 群密钥管理的明文操作
- 替客户端做消息加解密
---
## 4. 推荐服务拆分
```text
api-gateway
auth-service
virgil-jwt-service
conversation-service
message-service
group-service
sync-service
push-service
file-ticket-service
risk-device-service
```
### 各服务说明
#### api-gateway
- 统一入口
- 鉴权
- 请求限流
- trace 注入
#### auth-service
- 登录
- refresh
- logout
#### virgil-jwt-service
- 生成 Virgil JWT
- user/device 到 virgil identity 的映射
- 风控前置校验
#### conversation-service
- 单聊会话
- 会话设置
- 会话列表
#### message-service
- 接收密文 envelope
- 分配 message_id / seq
- 存储与 fanout
#### group-service
- 创建群
- 加人/踢人/退群
- 群资料
- 维护 group_key_version
#### sync-service
- bootstrap
- 增量消息
- 群事件同步
#### push-service
- message.new
- message.recall
- group.member_changed
- device.revoked
#### file-ticket-service
- 上传票据
- 下载票据
- 文件元信息
#### risk-device-service
- 设备状态
- 完整性校验
- 风险拦截
---
## 5. 服务端数据模型
## 5.1 用户与设备
```mermaid
erDiagram
USER ||--o{ DEVICE : owns
USER {
string user_id
string status
int64 created_at
}
DEVICE {
string device_id
string user_id
string platform
string device_model
string app_version
string virgil_identity
string status
int64 last_seen_at
}
```
## 5.2 会话与消息
```mermaid
erDiagram
CONVERSATION ||--o{ MESSAGE : contains
CONVERSATION {
string conversation_id
string type
string peer_key
string group_id
int64 created_at
}
MESSAGE {
string message_id
string conversation_id
string chat_type
string sender_user_id
string sender_device_id
string receiver_user_id
string group_id
int64 group_key_version
string content_type
int envelope_version
string cipher_suite
bytes ciphertext
bytes signature
int64 seq
int64 server_timestamp
}
```
## 5.3 群与群事件
```mermaid
erDiagram
GROUP ||--o{ GROUP_MEMBER : has
GROUP ||--o{ GROUP_KEY_EVENT : emits
GROUP {
string group_id
string conversation_id
string owner_user_id
string name
int64 group_key_version
string status
}
GROUP_MEMBER {
string group_id
string user_id
string role
string status
int64 join_version
int64 leave_version
}
GROUP_KEY_EVENT {
string event_id
string group_id
int64 group_key_version
string event_type
string operator_user_id
int64 created_at
}
```
---
## 6. 服务端接口设计
## 6.1 认证与设备
### 登录
```http
POST /api/v1/auth/login
```
### 刷新 token
```http
POST /api/v1/auth/refresh
```
### 登出
```http
POST /api/v1/auth/logout
```
### 注册设备
```http
POST /api/v1/devices/register
```
### 查询设备列表
```http
GET /api/v1/devices
```
### 吊销设备
```http
POST /api/v1/devices/{device_id}:revoke
```
---
## 6.2 Virgil JWT
### 获取 Virgil JWT
```http
POST /api/v1/security/virgil-jwt
```
请求:
```json
{
"device_id": "ios_a1"
}
```
响应:
```json
{
"virgil_jwt": "virgil_jwt_xxx",
"expires_in": 3600,
"virgil_identity": "u_1001:ios_a1"
}
```
---
## 6.3 会话
### 创建/获取单聊
```http
POST /api/v1/conversations/single
```
### 会话列表
```http
GET /api/v1/conversations
```
### 会话详情
```http
GET /api/v1/conversations/{conversation_id}
```
### 会话设置
```http
POST /api/v1/conversations/{conversation_id}/settings
```
---
## 6.4 消息
### 发送消息
```http
POST /api/v1/messages
```
### 批量发送
```http
POST /api/v1/messages:batchSend
```
### 拉取指定消息
```http
GET /api/v1/messages/{message_id}
```
### 撤回消息
```http
POST /api/v1/messages/{message_id}:recall
```
### 仅自己删除
```http
POST /api/v1/messages/{message_id}:deleteForMe
```
---
## 6.5 群组
### 创建群
```http
POST /api/v1/groups
```
### 群详情
```http
GET /api/v1/groups/{group_id}
```
### 群上下文
```http
GET /api/v1/groups/{group_id}/context
```
### 群成员列表
```http
GET /api/v1/groups/{group_id}/members
```
### 加人
```http
POST /api/v1/groups/{group_id}/members:add
```
### 移除成员
```http
POST /api/v1/groups/{group_id}/members:remove
```
### 退群
```http
POST /api/v1/groups/{group_id}:leave
```
### 解散群
```http
POST /api/v1/groups/{group_id}:dismiss
```
### 修改群资料
```http
POST /api/v1/groups/{group_id}/profile
```
---
## 6.6 文件
### 申请上传票据
```http
POST /api/v1/files/upload-ticket
```
### 上传完成
```http
POST /api/v1/files/{file_id}:complete
```
### 获取下载票据
```http
POST /api/v1/files/{file_id}/download-ticket
```
### 获取文件元信息
```http
GET /api/v1/files/{file_id}
```
---
## 6.7 同步
### 冷启动 bootstrap
```http
GET /api/v1/sync/bootstrap
```
### 增量消息同步
```http
GET /api/v1/sync/messages
```
### 群事件同步
```http
GET /api/v1/sync/group-events
```
---
## 6.8 回执与状态
### 已送达/已读
```http
POST /api/v1/messages/ack
```
### 批量已读
```http
POST /api/v1/conversations/{conversation_id}:markRead
```
### 输入中
```http
POST /api/v1/conversations/{conversation_id}/typing
```
---
## 6.9 风控与安全
### 预检查
```http
POST /api/v1/security/precheck
```
### 设备完整性上报
```http
POST /api/v1/security/integrity-report
```
---
## 7. 服务端核心流程
## 7.1 签发 Virgil JWT
```mermaid
sequenceDiagram
participant C as 客户端
participant J as Virgil JWT Service
participant A as Auth Service
participant R as Risk / Device Service
C->>J: /security/virgil-jwt
J->>A: 校验 access_token
A-->>J: 用户有效
J->>R: 校验 device_id / 风险状态
R-->>J: 允许或拒绝
J-->>C: 返回 virgil_jwt
```
## 7.2 消息接收与路由
```mermaid
sequenceDiagram
participant C as 客户端
participant M as Message Service
participant S as Sync Service
participant P as Push Service
participant DB as Metadata DB
C->>M: POST /messages
M->>DB: 存储 envelope
M->>DB: 分配 message_id / seq
M->>S: 写离线同步流
M->>P: 触发新消息推送
M-->>C: 返回 accepted
```
## 7.3 群成员变更
```mermaid
sequenceDiagram
participant A as 管理员客户端
participant G as Group Service
participant DB as Metadata DB
participant S as Sync Service
participant P as Push Service
A->>G: /groups/{id}/members:add
G->>DB: 更新群成员
G->>DB: group_key_version + 1
G->>S: 写入 group event
G->>P: 推送 group.member_changed
G-->>A: 返回最新 group_key_version
```
---
## 8. 服务端幂等与校验
## 8.1 幂等设计
### 发消息幂等键
推荐:
```text
sender_user_id + sender_device_id + client_message_id
```
### 创建群幂等
推荐使用:
```http
Idempotency-Key: <uuid>
```
## 8.2 消息接口校验项
- 当前用户是会话参与者
- `sender_device_id` 属于当前用户
- 单聊的 `receiver_user_id` 与会话匹配
- 群聊的 `group_id` 与会话匹配
- 当前用户是群成员
- `group_key_version` 合法
- `ciphertext` 长度不超过限制
## 8.3 Virgil JWT 接口校验项
- 业务 token 有效
- `device_id` 属于当前用户
- 设备状态为 active
- 未被吊销
- 风控未阻断
---
## 9. WebSocket / 推送事件建议
### WebSocket 事件
- `message.new`
- `message.recall`
- `message.ack`
- `group.member_changed`
- `group.profile_changed`
- `device.revoked`
- `security.force_logout`
### 推送原则
推送中不要放消息明文,建议只放:
- 会话 ID
- 发送方昵称
- 占位提示
---
## 10. 服务端风险点
- 若服务端误记录明文日志,会破坏 E2EE 边界
- 若文件下载链接长期有效,文件密文泄露面会扩大
- 若群成员变更后未提升 `group_key_version`,客户端可能使用旧上下文
- 若被吊销设备仍可获取 Virgil JWT会造成安全失控
- 若推送带明文,会绕过加密链路
---
## 11. 推荐实施路径
## 阶段 1单聊 MVP
实现:
- 登录
- Virgil JWT
- 单聊消息发送
- 增量同步
- 已读回执
## 阶段 2群聊
实现:
- 创建群
- 群成员管理
- group_key_version
- 群事件同步
## 阶段 3文件与恢复
实现:
- 文件票据
- 加密文件上传下载
- 新设备恢复
- 风控增强
---
## 12. 服务器总结
服务器在 Virgil Security 接入中的核心定位是:
- 不参与消息解密
- 不保存私钥
- 只处理密文、元数据和业务控制逻辑
具体来说,服务器负责:
- 身份认证
- 设备管理
- Virgil JWT 签发
- 密文消息接入、存储、路由
- 会话与群成员关系
- 文件票据
- 同步与推送
- 风控和设备吊销
这样才能既保留现有聊天系统的业务能力,又维持端到端加密的安全边界。