# 项目二:web-ssh项目 **Repository Path**: gjy/web-ssh-project ## Basic Information - **Project Name**: 项目二:web-ssh项目 - **Description**: web版ssh远程控制服务 - **Primary Language**: Unknown - **License**: AFL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-08-07 - **Last Updated**: 2026-08-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Web SSH 项目说明文档 本文件是 Web SSH 项目的完整说明文档,包含项目简介、从零开始的开发演进历程、项目结构、核心架构逻辑与详解、快速部署及运维指南。 --- ## 1. 项目简介 (Project Introduction) **Web SSH** 是一个基于 B/S 架构的轻量级 Web 终端应用,允许用户直接通过现代浏览器安全地连接并管理远程主机。 在运维工作中,传统的 SSH 工具(如 Putty、SecureCRT、Xshell 等)需要本地下载与安装,且配置不易跨设备同步。Web SSH 致力于通过 Web 技术栈(React + Node.js + SQLite)提供接近原生终端的流畅体验,并融入了现代 Web 界面设计前沿标准。 ### 核心亮点 - **沉浸式终端体验**:集成 `xterm.js` 及自适应插件,支持 256 色、富文本输出与流畅输入。 - **免密快速连接**:首创可选的“保存密码”本地持久化机制,再次连接时实现静默后台秒连,告别繁琐的弹窗输入。 - **可视化 SFTP 文件管理器**:无需切换工具(如 FileZilla),直接在终端窗口中一键打开 SFTP 文件浏览器,支持文件的双向上传与下载,并配有实时的传输百分比进度条。 - **午夜赛博玻璃视觉(Midnight Cyber-Glass)**:UI 全面采用轻量化高质感磨砂玻璃设计,配有柔和的多彩光晕背景,以及高仿真 3D 物理按键与双端对比色发光的语言切换器。 --- ## 2. 从零开始的开发演进历程 (Development Journey) ### 2.1 第一阶段:最小可行性产品 (MVP) 的诞生 最早的项目仅包含最基本的基础框架: - **后端**:使用 Express 暴露简单接口,引入 `ssh2`,利用基本 WebSocket 转发字符。 - **前端**:一个单纯黑色背景的 xterm.js 窗口,只支持单主机连接,没有任何账号注册或密码保护。 ### 2.2 第二阶段:引入安全性与多用户数据库 随着应用走向实用,安全成为首要考量: - **数据库引入**:集成嵌入式关系数据库 SQLite3,用于存储用户信息及各个主机的 IP、端口和用户名。密码采用 `bcrypt` 进行高强度哈希加密。 - **鉴权体系**:引入 JWT (JSON Web Token),并将其封锁在 `HttpOnly` 及 `SameSite=Lax` 安全 Cookie 中。 - **安全防线**:增加了内容安全策略 (CSP) 头部防御,加入了防 CSRF token,限制了 iframe 点击劫持。 ### 2.3 第三阶段:多标签页 (Tabs) 与高级 UI 视觉革命 为了能同时连接多台主机,并给用户带来视觉冲击: - **标签页架构**:在前端主面板设计了 Tab 栏,支持随时新建、切换和关闭不同的终端会话。 - **视觉升级**:放弃了市面上 Web SSH 通用的死板深灰背景,全面推翻重构为 **午夜赛博玻璃** 质感,加入背景光斑微动效,重绘了极具呼吸感的圆角按钮与输入框。 ### 2.4 第四阶段:细节打磨与高级交互优化 在基础功能与外观到位后,我们对产品细节进行了多次打磨: - **滚动查看主机**:当顶部连接的主机卡片过多时,Tab 栏支持横向拖拽/鼠标滚轮滑动滚动。 - **静默秒连**:增加“保存密码”选项,连接成功后密码存入本地加密字段。下次点击该主机卡片时,不再弹窗询问密码,直接秒连入命令行。 - **无感文件管理器**:在终端内部增加 SFTP 上传与下载按钮,能够调出远程服务器的文件目录浏览器,支持目录跳转与极佳的文件传输动态反馈。 ### 2.5 第五阶段:深度 Debug 与微动效完善(当前状态) 在此阶段,我们解决了最棘手的两个问题: 1. **彻底局限命令行界面(防止文字无限下坠)**: 通过在 `.terminal-wrapper` 和 `.terminal-container` 设置严格的 `overflow: hidden;`,并将 `.xterm` 强制约束为高度 `100%`,配合 `ResizeObserver`,彻底杜绝了文本向外延伸的顽疾。 2. **语言切换滑块丝滑滑动**: 排查并解决了 React 动态组件卸载重建的生命周期 Bug。将组件独立定义在 `App` 外并传入 props,实现了滑块在“中/EN”之间的真实滑动。加入了 3D 物理凹凸质感与双端对比色(蓝紫 vs 洋红)渐变,使其视觉效果达到工业级美化水准。 3. **命令行界面高对比度护眼暗色模式**: 将命令行面板(`.terminal-wrapper`)单独优化为高对比度的**深黑曜石色(Obsidian Dark Glass, rgba(15, 23, 42, 0.95))**,并将 xterm.js 前景文字调整为高易读性的亮灰色(`#cbd5e1`)。这既保障了各类全屏工具(如 `vim`、`less`)及 ANSI 彩色语法高亮在此处拥有完美的对比度与可读性,又与外部明亮的玻璃拟态仪表盘(Tabs、侧边栏)形成极具工业质感的视觉衬托。 4. **焦点强制复位防偏移(解决 Vim 上下频繁切换页面错行问题)**: 在频繁切换标签页或焦点切换时,由于 xterm.js 自动聚焦内部 textarea 文本框,浏览器原生焦点机制会强行对容器发起自动滚动以显示焦点元素,从而将 xterm 渲染的 canvas 向上或向下顶起偏移(约一到两行的高宽),造成视觉错位。我们为 `.terminal-area`、`.terminal-tab-pane` 以及组件根元素增加了严格的 `overflow: hidden;` 属性,并为 `.terminal-container` 容器绑定了 `scroll` 事件监听器,将任何自动滚动导致的 `scrollTop` 和 `scrollLeft` 瞬间复位至 `0`。这彻底确保了在任何切换操作下,画布绝不偏移,光标位置与逻辑行完全对齐。 --- ## 3. 目录与项目结构 (Project Structure) 项目采用典型的前后端分离开发目录,同时提供了生产一键集成脚本。 ```text web-ssh/ ├── README.md # 统一说明文档(本文档) ├── start.sh # 开发环境一键启停脚本 (双端口,热重载) ├── deploy.sh # 生产环境裸机部署脚本 ├── Dockerfile # Docker 多阶段构建镜像配置 ├── docker-compose.yml # Docker 容器编排配置文件 (Host 网络模式) ├── docker-deploy.sh # Docker 容器化一键部署脚本 ├── .gitignore # Git 忽略规则 (过滤持久化 data 目录等) ├── .dockerignore # Docker 构建忽略规则 ├── data/ # Docker 运行时数据库持久化挂载目录 ├── logs/ # 全局日志文件夹 ├── backend/ # Node.js 后端服务代码 │ ├── auth.js # 用户身份认证(JWT、bcryptjs 加密) │ ├── db.js # SQLite3 数据库交互及迁移逻辑 │ ├── index.js # Express API 路由入口及静态资源托管 │ └── ssh.js # ssh2 底层协议、PTY 桥接及 SFTP 流传输核心 └── frontend/ # React 前端工程代码 ├── dist/ # 生产打包产物 └── src/ # 核心交互视图 (Terminal, FileManager, 等) ``` --- ## 4. 核心写代码逻辑与架构设计 (Core Code Logic) ### 4.1 终端双向流动架构 (WebSocket Bridge) 终端的操作对延迟极其敏感,传统的 HTTP 轮询无法满足要求。我们采用 **Socket.io** 建立全双工通信: 1. 前端 `xterm.js` 捕获用户的每一个键盘输入(通过 `term.onData`),直接通过 WebSocket `socket.emit('data')` 发送至后端。 2. 后端接收到字符后,写入对应远程主机的底层 `ssh2` 通信流(`stream.write`)。 3. 远程 Linux 系统执行后,输出结果字符集,通过 `stream.on('data')` 传回后端。 4. 后端再次通过 WebSocket `socket.emit('data')` 传给前端,前端调用 `term.write` 渲染在屏幕上。 ### 4.2 动态自适应屏幕尺寸 (Fit Algorithm) 为使终端窗口大小能够完美撑满浏览器界面,我们结合了 Xterm.js 的 `FitAddon`: 1. 前端渲染终端容器 `.terminal-container`。 2. 当容器发生变化(如拖拽窗口、收起侧边栏)时,前端利用 `ResizeObserver` 捕获最新的宽高像素。 3. `FitAddon` 计算当前字号下,该像素空间可容纳的最大行列数(`cols` / `rows`),并调整前端终端大小。 4. 前端通过 WebSocket 向后端发送 `resize` 事件,后端调用远程 SSH 会话的 `stream.setWindow` 动态同步远端的伪终端(PTY)窗口大小。这样可以保证如 `top`、`vim` 等复杂全屏命令不会出现字符换行错乱。 ### 4.3 SFTP 内存无痕流传输与多任务队列 本项目的上传与下载采用了**纯内存流式转发**及**高并发安全的队列编排**机制: - **无痕下载 (Download)**:前端请求下载时,后端与远端主机建立 SFTP 读文件流,直接通过 WebSocket 分片(Chunk)源源不断发送给前端。针对**整个文件夹下载**场景,后端设计了高效的流式打包方案(将 `tar -czf -` 命令的 stdout 直接通过 Socket 透传),实现**零中间文件落地**。 - **多文件批量上传 (Upload)**:全面支持通过 HTML5 `` 进行多文件及整个文件夹结构的批量上传。前端实现了严格的异步上传队列(Queue),逐一通过 `FileReader` 拆解分片发送;后端在每个文件写完后,严谨地监听底层 SSH2 的 `close` 生命周期信号来释放句柄(杜绝了传统 `finish` 事件可能吞噬状态导致卡死的并发 Bug),并自动递归预创建远端所需的嵌套目录(`mkdir -p`),保证了百兆/多文件级别的稳定可靠传输。 --- ## 5. 核心模块详解 (In-depth File Walkthrough) ### 5.1 终端管理器:`TerminalComponent.jsx` 本组件封装了 Xterm 的初始化与事件治理: - **初始化连接**:在输入或静默读取本地缓存密码后,调用 `doConnect` 建立后端 Socket 握手并渲染 PTY 容器。 - **事件治理与内存管理**:将 `ResizeObserver`、`window` 监听器统合在 React 的 `useEffect` 中,严格在依赖项更新或组件销毁时注销,彻底消除内存泄露。 - **非活跃状态适配**:利用 `isActive` 机制,在用户切换标签页时才调用 `fit()`,避免因隐藏容器宽高为 0 导致错位。 ### 5.2 语言切换器:`App.jsx` 中的 `LangSwitcher` - **DOM Identity 保持**:将 `LangSwitcher` 声明移出 `App` 外部,使得在语言状态切换时 React 能够复用 DOM 节点,保留其过渡位移动效。 - **循环切换逻辑**:支持“点击未选中项切换语言,点击已选中项反向切换”的双向交互。 ### 5.3 样式系统:`index.css` - **毛玻璃与光斑**:使用 `backdrop-filter: blur(28px) saturate(180%)`,配合 body 上的两个动态漂浮模糊光斑,营造高级透光的赛博玻璃感。 - **3D 质感滑块**:为语言切换器设置了 `inset 0 1.5px 3px` 的内阴影轨道,并在 `.lang-slider` 加上了 `inset 0 1px 0 #ffffff`(高光反光边缘),模拟出真实的凸起按钮质感。 - **双端色彩对比**:利用 `.zh-active` (蓝紫色 `#4f46e5` 加发光) 与 `.en-active` (洋红色 `#d946ef` 加发光) 在切换时,让滑块在两端呈现不同的主题色彩。 --- ## 6. 技术栈与功能特性 ### 6.1 前端 (Frontend) - **核心框架**: React 18 + Vite 构建工具 - **路由管理**: React Router DOM (v6) - **终端模拟器**: Xterm.js 及其插件 (`@xterm/addon-fit`) - **WebSocket 客户端**: Socket.io-client ### 6.2 后端 (Backend) - **运行环境**: Node.js - **Web 框架**: Express.js - **实时通信**: Socket.io Server - **SSH 核心驱动**: `ssh2` 库实现底层的 SSH2 协议连接与 SFTP 流管理。 - **数据持久化**: SQLite3 嵌入式存储(数据库位于 `backend/database.sqlite` 或外部挂载卷)。 - **加密与安全**: `bcryptjs` 纯 JS 实现处理哈希,兼容各类环境;`jsonwebtoken` 处理 JWT 鉴权。 --- ## 7. 快速开始 (Quick Start) ### 7.1 开发环境启动 (Development) 项目根目录下提供了 `start.sh`,可用于启动开发环境服务(前后端分离,双端口运行): ```bash # 启动开发服务 ./start.sh start # 停止开发服务 ./start.sh stop ``` ### 7.2 生产环境部署 (Production) 对于正式环境,我们提供了 `deploy.sh`。它会自动将前端构建为静态资源,并由 Node.js 后端统一在一个端口提供服务。 ```bash # 一键自动构建并后台启动生产环境服务 ./deploy.sh ``` ### 7.3 容器化部署 (Docker) 我们强烈推荐使用 Docker 容器化方案进行部署,完全隔离环境,不会产生依赖冲突,并提供持久化支持。 ```bash # 赋予权限并启动 chmod +x docker-deploy.sh ./docker-deploy.sh ``` 数据文件(数据库)会自动持久化存储到项目根目录下的 `data` 文件夹中。 ### 7.4 CI/CD 自动化流水线 (Jenkins) 本项目深度支持企业级 Jenkins Pipeline (Groovy) 自动化交付。在配套的部署流水线设计中,涵盖了以下运维标准操作: - **状态不可变同步**:通过 `git fetch && git reset --hard` 取代 `git pull`,防范线上热更引起的代码分叉冲突。 - **磁盘健康治理**:构建前强制触发 `docker system prune -f`,避免由于高频构建产生的僵尸镜像耗尽服务器磁盘空间(No space left on device)。 - **无感多阶段构建**:结合项目中内置的 `Dockerfile` (基于 `node:20-slim`) 自动编译并推送到远端云镜像仓库 (TCR),实现跨宿主机弹性扩容。 ### 7.5 访问界面 在成功启动后,使用浏览器访问: - **生产/容器环境地址** (推荐): `http://localhost:3000` - 开发环境地址: `http://localhost:5173` - **默认账号**: `admin` - **默认密码**: `admin123` --- ## 8. 安全性与迁移维护 1. **鉴权安全**: Token 通过 `HttpOnly`, `SameSite=Lax` 的安全 Cookie 下发,WebSocket 连接时也会进行 Token 二次校验。 2. **Web 安全防御**: 启用了 `X-Frame-Options` 防御点击劫持,开启了 `X-Content-Type-Options: nosniff`,以及动态生成的 `Content-Security-Policy`。 3. **数据备份**: 项目的全部核心安全与状态数据保存在以下位置(已在 `.gitignore` 中被安全过滤排除): - 如果您使用 Docker 容器化部署,所有持久化数据都在宿主机根目录下的 `data/` 文件夹中。 - 如果您直接运行环境,数据位于: - `backend/database.sqlite` (用户账号及主机列表) - `backend/jwt_secret.txt` (JWT 签名密钥) 备份或迁移服务器时,仅需要将 `data/` 文件夹(或上述两个单文件)打包拷贝到新环境即可无缝恢复所有配置。