diff --git a/RDP_Integration_Plan.md b/RDP_Integration_Plan.md new file mode 100644 index 0000000..1f16e6d --- /dev/null +++ b/RDP_Integration_Plan.md @@ -0,0 +1,130 @@ +# RDP 集成计划 + +## 整体架构思路 + +我们将采用与 `test-rdp` 类似的架构: + +1. **前端 (`packages/frontend`):** 使用 `guacamole-common-js` 库在 `RemoteDesktopModal.vue` 组件中渲染 RDP 界面并处理用户输入。 +2. **后端 API (`packages/backend`):** 提供一个接口,根据连接 ID 从数据库获取连接信息,并生成一个加密的 Guacamole 连接令牌 (`token`)。 +3. **WebSocket 代理:** 需要一个服务来处理前端和 `guacd` 之间的 WebSocket 通信。我们将采用 `test-rdp` 中的 `guacamole-lite` 方案,但将其作为一个**独立的服务**运行,与主后端分开。 +4. **Guacamole Daemon (`guacd`):** 这是 Guacamole 的核心组件,需要单独运行,负责实际的 RDP 协议转换。 + +## 详细计划步骤 + +### 1. 后端 (`packages/backend`) + +* **创建 Guacamole 服务 (`guacamole.service.ts`):** + * 在 `packages/backend/src/services/` 目录下创建新文件 `guacamole.service.ts`。 + * 实现一个 `generateConnectionToken` 方法: + * 接收 `ConnectionInfo` 对象和加密密钥作为参数。 + * 将 `ConnectionInfo` 构造成 Guacamole 所需的 JSON 结构(包含 `type: 'rdp'`, `settings: {...}`)。 + * 使用 `crypto` 模块和 `AES-256-CBC` 算法,以及一个 32 字节的加密密钥(从配置加载)来加密这个 JSON 字符串。 + * 返回 Base64 编码后的加密令牌(格式需与 `guacamole-lite` 解密时兼容,参考 `test-rdp/backend/src/server.ts` 的 `encryptToken` 函数)。 +* **添加 API 端点 (`connections.controller.ts`, `connections.routes.ts`):** + * 在 `ConnectionsController` 中添加一个新方法,例如 `getRdpToken`。 + * 添加一个新的路由,例如 `GET /api/connections/:id/rdp-token`,指向 `getRdpToken` 方法。 + * `getRdpToken` 方法: + * 从请求参数中获取 `id`。 + * 注入并使用 `ConnectionService` 根据 `id` 获取完整的 `ConnectionInfo`(包括主机、端口、用户名、密码等)。 + * 注入并使用新创建的 `GuacamoleService` 的 `generateConnectionToken` 方法生成令牌。 + * 将生成的令牌以 JSON 格式 (`{ token: "..." }`) 返回给前端。 +* **配置:** + * 在后端配置中(例如通过环境变量 `.env` 或配置文件)定义 `GUACAMOLE_ENCRYPTION_KEY`。**这个密钥必须是 32 字节长**,并且需要与后面运行的 `guacamole-lite` 服务使用的密钥相同。 + * 确保后端能正确加载和使用这个密钥。 +* **依赖:** + * 确保 `packages/backend/package.json` 中包含 `crypto` (Node.js 内置)。 + +### 2. 前端 (`packages/frontend`) + +* **`RemoteDesktopModal.vue`:** + * **Props:** 确认组件接收 `connection: ConnectionInfo` 作为 prop。 + * **模板:** 在 `