ahserver/aidocs/p2p_middleware.md
2025-10-05 12:07:12 +08:00

276 lines
7.0 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.

以下是为提供的 Python 代码编写的 **Markdown 格式技术文档**,涵盖了类的功能、依赖、中间件逻辑以及各方法的说明。
---
# `P2pLayer` 技术文档
## 概述
`P2pLayer` 是一个基于 `aiohttp` 的中间件组件,用于在 Web 请求处理流程中集成点对点P2P加密通信功能。该模块通过条件启用 P2P 加密层,并在请求/响应过程中实现握手、解码和编码操作,以保障通信安全。
此模块依赖于 `p2psc` 库中的 `PubkeyHandler``P2psc` 类,实现公钥管理和端到端加密逻辑。
---
## 依赖项
- [`aiohttp`](https://docs.aiohttp.org/):异步 HTTP 客户端/服务器框架。
- `p2psc.pubkey_handler.PubkeyHandler`:负责管理本地公钥与远程节点身份认证。
- `p2psc.p2psc.P2psc`:核心 P2P 安全通信类,支持加密握手与数据加解密。
- `getConfig()`:全局配置获取函数(外部定义,需确保可用)。
> ⚠️ 注意:`getConfig()` 函数未在此文件中定义,应由项目其他部分提供,返回包含配置树的对象。
---
## 类定义
```python
class P2pLayer
```
### 功能
`P2pLayer` 封装了 P2P 加密通信的初始化与中间件逻辑。根据配置决定是否启用加密传输,并在启用时拦截请求/响应流进行加解密处理。
---
## 初始化 (`__init__`)
```python
def __init__(self)
```
### 描述
初始化 `P2pLayer` 实例并根据配置决定是否启用 P2P 加密功能。
### 流程
1. 初始化 `self.p2pcrypt = False`
2. 调用 `getConfig()` 获取系统配置。
3. 检查配置项 `config.website.p2pcrypt`
- 若为 `True`,则启用 P2P 加密(设置 `self.p2pcrypt = True`),并初始化相关组件;
- 否则跳过初始化,后续中间件将直接透传请求。
4. 如果启用了加密:
- 创建 `PubkeyHandler` 实例用于密钥管理;
- 使用 handler 及其自身 ID 初始化 `P2psc` 实例。
### 属性
| 属性 | 类型 | 说明 |
|------|------|------|
| `p2pcrypt` | `bool` | 是否启用 P2P 加密模式 |
| `handler` | `PubkeyHandler` | 公钥处理器,管理本地/远程身份 |
| `p2p` | `P2psc` | P2P 安全通信核心实例 |
> ✅ 提示:仅当 `p2pcrypt` 为 `True` 时,`handler` 和 `p2p` 才会被创建。
---
## 中间件:`p2p_middle`
```python
@web.middleware
async def p2p_middle(self, request, handler)
```
### 描述
Aiohttp 异步中间件,用于拦截进入的 HTTP 请求并执行 P2P 加密相关处理。
### 执行逻辑
| 条件 | 行为 |
|------|------|
| `not self.p2pcrypt` | 直接调用原始 handler不进行任何加密处理 |
| 请求头含 `P2pHandShake` | 调用 `self.p2p_handshake(request)` 进行密钥交换 |
| 请求头含 `P2pdata` | 解密请求 → 处理 → 加密响应 |
| 其他情况 | 直接调用 handler明文通行 |
### 详细流程
```text
开始
├─ 是否禁用 p2pcrypt
│ └─ 是 → 直接返回 handler(request)
├─ 是否存在 "P2pHandShake" 头?
│ └─ 是 → 返回 await p2p_handshake(request)
├─ 是否存在 "P2pdata" 头?
│ ├─ 是 →
│ │ 1. await p2p_decode_request(request)
│ │ 2. resp = await handler(decoded_request)
│ │ 3. return await p2p_encode_response(resp)
└─ 默认 → 返回 await handler(request)
```
### 注意事项
- 当前代码存在拼写错误:
- `if not p2pscrypr:` ❌ → 应为 `if not self.p2pcrypt:`
- `resturen` ❌ → 应为 `return`
- `request.header.get` ❌ → 应为 `request.headers.get`
- 正确代码应如下:
```python
@web.middleware
async def p2p_middle(self, request, handler):
if not self.p2pcrypt:
return await handler(request)
if request.headers.get('P2pHandShake', None):
return await self.p2p_handshake(request)
if request.headers.get('P2pdata', None):
request = await self.p2p_decode_request(request)
resp = await handler(request)
return await self.p2p_encode_response(resp)
return await handler(request)
```
---
## 方法说明
### `p2p_handshake(request)`
```python
async def p2p_handshake(self, request)
```
#### 描述
处理客户端发起的 P2P 安全握手请求(如密钥交换)。当前为空实现(`pass`),需子类或后续扩展完成具体协议逻辑。
#### 参数
- `request` (`aiohttp.web.Request`)HTTP 请求对象
#### 返回值
- 通常应返回 `aiohttp.web.Response` 对象,携带握手响应数据(如公钥、会话密钥等)
#### 示例场景
- TLS-like 密钥协商
- Diffie-Hellman 或 Noise 协议集成
---
### `p2p_decode_request(request)`
```python
async def p2p_decode_request(self, request)
```
#### 描述
对接收到的加密请求体进行解密和解析,还原为标准 `request` 对象。
#### 参数
- `request`:携带加密数据的原始请求
#### 返回值
- 解密后的 `request` 对象(可能包装新 body 或附加上下文字段)
#### 待实现内容
- 读取请求体
- 使用 `self.p2p.decrypt()` 解密
- 重构 JSON/body 数据
- 替换 `request._payload` 或使用自定义 Request 子类
---
### `p2p_encode_response(response)`
```python
async def p2p_encode_response(self, response)
```
#### 描述
将正常的 HTTP 响应内容加密后封装,返回给客户端。
#### 参数
- `response` (`aiohttp.web.Response`):原始响应对象
#### 返回值
- 加密后的响应对象(通常修改 body 并添加头部如 `Content-Encoding: p2p`
#### 当前实现
```python
return response
```
> 🔴 当前为占位实现,未实际加密。需要补充:
>
> - 序列化响应内容
> - 使用 `self.p2p.encrypt()` 加密
> - 设置 `Content-Type` 或自定义头标识加密类型
> - 构造新的 `StreamResponse` 或 `Response` 返回
---
## 配置要求
确保配置结构中包含以下字段:
```python
config = {
"website": {
"p2pcrypt": True # 或 False控制是否启用 P2P 加密
}
}
```
可通过环境变量、YAML 文件或其他方式加载。
---
## 使用示例(伪代码)
```python
app = web.Application(middlewares=[p2player.p2p_middle])
p2player = P2pLayer()
web.run_app(app)
```
---
## 已知问题 / 待修复 Bug
| 问题 | 位置 | 说明 |
|------|------|------|
| 拼写错误 `p2pscrypr` | 第10行 | 应为 `self.p2pcrypt` |
| `resturen` 错误 | 第12行 | 应为 `return` |
| `request.header``.headers` | 第15行 | 属性名错误 |
| `p2p_handshake` 无实现 | 第20行 | 需补充握手逻辑 |
| 加解密方法为空 | 第2429行 | 仅为骨架,需具体实现 |
---
## 总结
`P2pLayer` 提供了一个可插拔的 P2P 加密通信中间件框架,适用于需要端到端安全传输的去中心化 Web 服务。虽然目前大部分功能尚未实现,但其设计清晰,具备良好的扩展性。
建议下一步:
- 修复语法错误
- 实现握手与加解密逻辑
- 添加单元测试与集成测试
- 支持超时、重试、会话缓存等机制
---
📌 **版本信息**v0.1(草案)
📅 **最后更新**2025-04-05