# 数据库连接工具 **Repository Path**: hua-xiong/database-connection-tool ## Basic Information - **Project Name**: 数据库连接工具 - **Description**: react+vite+nodejs - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-24 - **Last Updated**: 2026-07-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # DB Manager - 数据库管理工具 一个前后端分离的 Web 数据库管理工具,支持 MySQL 数据库的连接、浏览、查询与数据编辑。 ## 技术栈 | 层级 | 技术 | |------|------| | 前端框架 | React 18 + TypeScript | | 构建工具 | Vite 5 | | UI 组件库 | Ant Design 5 + @ant-design/icons | | 代码编辑器 | CodeMirror 6(@codemirror/lang-sql / @codemirror/theme-one-dark) | | HTTP 客户端 | Axios | | 后端框架 | Express 4 (Node.js) | | 数据库驱动 | mysql2(连接池模式) | | 认证 | jsonwebtoken(JWT 认证) | | 环境变量 | dotenv | | 目标数据库 | MySQL 5.7+ / MariaDB | ## 项目结构 ``` db-manager/ ├── client/ # 前端项目 │ ├── index.html # 入口 HTML │ ├── package.json │ ├── vite.config.ts # Vite 配置(含 API 代理) │ ├── tsconfig.json │ └── src/ │ ├── main.tsx # 应用入口 │ ├── App.tsx # 根组件(布局与状态管理) │ ├── App.css # 全局样式 │ ├── services/ │ │ └── api.ts # API 封装(Axios 实例 + 接口函数) │ ├── utils/ │ │ ├── rowUtils.ts # 行数据工具(值格式化、主键提取) │ │ └── exportUtils.ts # 数据导出(CSV / JSON / SQL) │ └── components/ │ ├── ConnectionBar.tsx # 数据库连接栏 │ ├── DbTree.tsx # 数据库/表资源树 │ ├── SqlEditor.tsx # SQL 查询编辑器 │ ├── DataView.tsx # 数据浏览与 CRUD │ └── TableStructure.tsx # 表结构查看器 │ └── server/ # 后端项目 ├── package.json ├── .env.example # 环境变量示例文件 └── src/ ├── index.js # Express 服务入口 ├── db.js # MySQL 连接池管理 ├── middleware/ │ └── auth.js # JWT 认证中间件 └── routes/ ├── connection.js # 连接管理路由 ├── databases.js # 数据库列表路由 ├── tables.js # 表列表与结构路由 ├── rows.js # 表数据 CRUD 路由 └── query.js # SQL 查询路由 ``` ## 功能特性 - **数据库连接管理**:支持指定主机、端口、用户名、密码和默认数据库,连接/断开一键操作,连接成功后返回 JWT Token - **数据库资源浏览**:树形展示所有数据库及下表,懒加载子节点 - **SQL 查询编辑器**:基于 CodeMirror 6,支持 SQL 语法高亮、行号显示、Ctrl+Enter 快捷键执行、Tab 缩进、查询历史记录 - **只读安全查询**:仅允许 SELECT / SHOW / DESCRIBE / EXPLAIN / WITH 语句,防止误操作 - **数据浏览**:分页表格展示表数据,支持双击单元格编辑、行删除、新增记录 - **表结构查看**:展示列名、类型、是否可空、键类型、默认值、额外信息、注释 - **数据导出**:支持将查询结果或表数据导出为 CSV、JSON、SQL 三种格式 - **连接状态持久**:顶部连接栏实时显示连接状态,断开后自动清空资源树 - **端口占用自愈**:服务端启动时若端口被占用自动释放并重试 - **界面体验**:亮色/暗色主题切换、点击涟漪特效、骨架屏加载占位、侧边栏折叠 ## 快速开始 ### 环境要求 - Node.js >= 18 - npm >= 9 - MySQL 5.7+(或其他兼容 MySQL 协议的数据库) ### 1. 安装依赖 ```bash # 安装后端依赖 cd server npm install # 配置环境变量(首次运行) cp .env.example .env # 编辑 .env,将 JWT_SECRET 替换为随机字符串(可用 openssl rand -base64 64 生成) # 安装前端依赖 cd ../client npm install ``` ### 2. 启动服务 ```bash # 启动后端(默认端口 3001) cd server npm run dev # 启动前端开发服务器(默认端口 5173) cd ../client npm run dev ``` ### 3. 访问 浏览器打开 `http://localhost:5173`,在顶部连接栏输入 MySQL 连接信息后点击"连接"即可开始使用。 > 前端开发服务器已配置 `/api` 代理到 `http://localhost:3001`,无需单独配置跨域。 ### 生产构建 ```bash cd client npm run build # 输出到 client/dist/ ``` 构建产物为静态文件,可部署到任意 HTTP 服务器。后端需单独部署 `server/` 目录。 ## API 文档 所有接口前缀为 `/api`,请求与响应均为 JSON 格式。 ### 1. 连接管理 #### 连接数据库 ``` POST /api/connect ``` **请求体** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | host | string | 是 | 数据库主机地址 | | port | number | 否 | 端口号(默认 3306) | | user | string | 是 | 用户名 | | password | string | 否 | 密码 | | database | string | 否 | 默认数据库 | **成功响应 (200)** ```json { "success": true, "message": "数据库连接成功", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } ``` **错误响应 (400 / 500)** ```json { "error": "主机地址和用户名不能为空" } ``` #### 断开连接 ``` POST /api/disconnect ``` **成功响应 (200)** ```json { "success": true, "message": "已断开连接" } ``` #### 获取连接状态 ``` GET /api/status ``` **成功响应 (200)** ```json { "connected": true } ``` --- ### 2. 数据库 #### 获取数据库列表 ``` GET /api/databases ``` **成功响应 (200)** ```json { "databases": ["mysql", "information_schema", "my_db"] } ``` --- ### 3. 表 #### 获取表列表 ``` GET /api/tables?database={db_name} ``` **查询参数** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | database | string | 是 | 数据库名 | **成功响应 (200)** ```json { "tables": ["users", "orders", "products"] } ``` #### 获取表结构 ``` GET /api/tables/{database}/{table}/structure ``` **路径参数** | 参数 | 类型 | 说明 | |------|------|------| | database | string | 数据库名 | | table | string | 表名 | **成功响应 (200)** ```json { "columns": [ { "Field": "id", "Type": "int(11)", "Null": "NO", "Key": "PRI", "Default": null, "Extra": "auto_increment", "Comment": "主键 ID" } ] } ``` --- ### 4. 行数据 #### 分页获取行数据 ``` GET /api/tables/{database}/{table}/rows?page=1&pageSize=20 ``` **查询参数** | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | page | number | 1 | 页码(最小 1) | | pageSize | number | 20 | 每页条数(最小 1,最大 200) | **成功响应 (200)** ```json { "rows": [ { "id": 1, "name": "Alice", "email": "alice@example.com" } ], "total": 150, "page": 1, "pageSize": 20 } ``` #### 插入行 ``` POST /api/tables/{database}/{table}/rows ``` **请求体**(JSON 对象,键为列名,值为字段值) ```json { "name": "Bob", "email": "bob@example.com" } ``` **成功响应 (200)** ```json { "success": true, "insertId": 151, "affectedRows": 1 } ``` #### 更新行 ``` PUT /api/tables/{database}/{table}/rows ``` **请求体** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | primaryKey | object | 是 | 主键条件,如 `{ "id": 1 }` | | (其他字段) | any | 否 | 需要更新的列及新值 | ```json { "primaryKey": { "id": 1 }, "name": "Alice Updated", "email": "newalice@example.com" } ``` **成功响应 (200)** ```json { "success": true, "affectedRows": 1 } ``` #### 删除行 ``` DELETE /api/tables/{database}/{table}/rows ``` **请求体** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | primaryKey | object | 是 | 主键条件,如 `{ "id": 1 }` | ```json { "primaryKey": { "id": 1 } } ``` **成功响应 (200)** ```json { "success": true, "affectedRows": 1 } ``` --- ### 5. SQL 查询 #### 执行 SQL 查询 ``` POST /api/query ``` **请求体** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | sql | string | 是 | SQL 语句(仅允许 SELECT / SHOW / DESCRIBE / EXPLAIN / WITH) | ```json { "sql": "SELECT * FROM users WHERE status = 'active' LIMIT 10" } ``` **成功响应 (200)** ```json { "columns": ["id", "name", "email"], "rows": [ { "id": 1, "name": "Alice", "email": "alice@example.com" } ], "rowCount": 1 } ``` **错误响应 (403)** ```json { "error": "仅允许只读查询(SELECT / SHOW / DESCRIBE / EXPLAIN)", "message": "写操作请通过数据表格编辑功能完成" } ``` --- ### 通用错误格式 所有接口在发生错误时返回统一的 JSON 结构: ```json { "error": "错误概述(面向用户)", "message": "详细错误信息(开发环境可见)" } ``` HTTP 状态码遵循语义: - `200` 成功 - `400` 请求参数错误 - `401` 未认证 —— Token 缺失、无效或过期(除 `/api/status`、`/api/connect`、`/api/disconnect` 外均需认证) - `403` 操作被禁止(如非只读 SQL) - `500` 服务器内部错误 ## 安全说明 ### JWT 认证 - **认证流程**:用户连接数据库成功后,服务端签发 JWT Token(有效期 24 小时),客户端后续请求需在 `Authorization` 头中携带 `Bearer `。 - **免检端点**:`GET /api/status`、`POST /api/connect`、`POST /api/disconnect` 无需携带 Token,其余所有接口均需通过认证中间件校验。 - **Token 过期**:超过 24 小时后 Token 自动失效,客户端需重新调用 `/api/connect` 获取新 Token。 ### 环境变量管理 - 敏感配置(如 JWT 签名密钥 JWT_SECRET)通过 `.env` 文件注入,不写入代码。 - 仓库提供 `.env.example` 作为模板,部署时复制为 `.env` 并填入实际值。 - `.env` 已加入 `.gitignore`,确保密钥不被提交到版本控制。 ### SQL 注入防护 - **白名单前缀过滤**:`/api/query` 接口检查 SQL 语句是否以 `SELECT`、`SHOW`、`DESCRIBE`、`EXPLAIN`、`WITH` 开头,拒绝任何写操作。注意此机制基于前缀匹配,仅覆盖以这些关键字开头的单条语句,不防御内联写操作或绕过前缀的复杂注入场景。 - **参数化标识符**:各路由在拼接表名/数据库名等标识符时使用 mysql2 的 `??` 占位符转义,但实际值绑定仍依赖调用处的编码规范。 - **连接信息隔离**:数据库连接凭据仅保存在服务端内存中,不写入日志或持久化存储。 - **端口自愈机制**:服务启动时若 `EADDRINUSE` 会自动释放端口后重试,避免僵尸进程占用。 - **优雅退出**:监听 `SIGTERM` / `SIGINT` 信号,关闭 HTTP 服务并释放连接池。 - **前端开发代理**:Vite 开发服务器配置了 `/api` 代理,避免浏览器跨域问题,且不暴露后端真实地址。 - **生产环境建议**: - 将 `NODE_ENV=production` 设置为生产环境,隐藏详细错误信息。 - 使用 `openssl rand -base64 64` 生成强随机 JWT_SECRET。 - 为 MySQL 连接使用只读账号或最小权限账号。 - 在前端构建产物前部署反向代理(如 Nginx)处理静态文件与 API 转发。 - 考虑添加请求频率限制(rate limiting)防止暴力破解或资源滥用。 ## License 本项目仅供学习与内部使用。