更改验证
This commit is contained in:
parent
00617621f9
commit
9e85e64345
34
README.md
34
README.md
@ -110,16 +110,19 @@
|
|||||||
## 💻 技术栈
|
## 💻 技术栈
|
||||||
|
|
||||||
### 后端
|
### 后端
|
||||||
|
|
||||||
- **PHP 7.4+**:Web服务器端逻辑
|
- **PHP 7.4+**:Web服务器端逻辑
|
||||||
- **Python 3.6+**:后台监控服务
|
- **Python 3.6+**:后台监控服务
|
||||||
- **SQLite 3**:轻量级数据库
|
- **SQLite 3**:轻量级数据库
|
||||||
|
|
||||||
### 前端
|
### 前端
|
||||||
|
|
||||||
- **HTML5/CSS3**:页面结构和样式
|
- **HTML5/CSS3**:页面结构和样式
|
||||||
- **JavaScript**:交互逻辑
|
- **JavaScript**:交互逻辑
|
||||||
- **响应式设计**:支持移动端访问
|
- **响应式设计**:支持移动端访问
|
||||||
|
|
||||||
### 依赖库
|
### 依赖库
|
||||||
|
|
||||||
- **PHP**: cURL, PDO-SQLite
|
- **PHP**: cURL, PDO-SQLite
|
||||||
- **Python**: requests, schedule, sqlite3
|
- **Python**: requests, schedule, sqlite3
|
||||||
|
|
||||||
@ -164,13 +167,15 @@ chmod 755 app/install.sh
|
|||||||
|
|
||||||
首次访问会自动跳转到配置页面,添加第一个VPS平台配置。
|
首次访问会自动跳转到配置页面,添加第一个VPS平台配置。
|
||||||
|
|
||||||
|
设置访问密码后,进入 `index.php` 或 `config_add.php` 时需先输入访问密码(POST 方式验证),验证成功后建立 PHP 会话(有效期 30 分钟,操作自动续期)。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⚙️ 配置说明
|
## ⚙️ 配置说明
|
||||||
|
|
||||||
### 添加VPS平台配置
|
### 添加VPS平台配置
|
||||||
|
|
||||||
1. 访问 `config_add.php?pass=YOUR_API_PASS`
|
1. 访问 `config_add.php`,首次访问需先设置访问密码
|
||||||
2. 填写配置信息:
|
2. 填写配置信息:
|
||||||
- **API标识**:自定义名称(唯一)
|
- **API标识**:自定义名称(唯一)
|
||||||
- **网站类型**:选择平台(目前支持魔方平台)
|
- **网站类型**:选择平台(目前支持魔方平台)
|
||||||
@ -184,6 +189,7 @@ chmod 755 app/install.sh
|
|||||||
### 配置示例
|
### 配置示例
|
||||||
|
|
||||||
**魔方平台配置**:
|
**魔方平台配置**:
|
||||||
|
|
||||||
```
|
```
|
||||||
API标识: 核云IDC
|
API标识: 核云IDC
|
||||||
网站类型: 魔方平台
|
网站类型: 魔方平台
|
||||||
@ -196,6 +202,7 @@ API密钥: your_api_key
|
|||||||

|

|
||||||
|
|
||||||
⚠️ **重要提示**:
|
⚠️ **重要提示**:
|
||||||
|
|
||||||
- 网站链接只填写根域名,不要包含 `/v1` 或 `/api` 等路径
|
- 网站链接只填写根域名,不要包含 `/v1` 或 `/api` 等路径
|
||||||
- API标识必须唯一,不能重复
|
- API标识必须唯一,不能重复
|
||||||
- 确保账户和密码正确
|
- 确保账户和密码正确
|
||||||
@ -208,14 +215,18 @@ API密钥: your_api_key
|
|||||||
|
|
||||||
#### 查看VPS列表
|
#### 查看VPS列表
|
||||||
|
|
||||||
访问 `index.php?pass=YOUR_API_PASS`,可以看到:
|
访问 `index.php`,输入访问密码登录后即可看到:
|
||||||
|
|
||||||
- 按配置分组的VPS列表
|
- 按配置分组的VPS列表
|
||||||
- 每个VPS的状态、IP、配置信息
|
- 每个VPS的状态、IP、配置信息
|
||||||
- 实时统计数据
|
- 实时统计数据
|
||||||
|
|
||||||
|
> 登录会话有效期 30 分钟(滑动过期),每次请求新数据会自动续期;超过 30 分钟无操作需重新登录。
|
||||||
|
|
||||||
#### 操作VPS
|
#### 操作VPS
|
||||||
|
|
||||||
每个VPS卡片提供三个操作按钮:
|
每个VPS卡片提供三个操作按钮:
|
||||||
|
|
||||||
- **⚡ 开机**:启动VPS
|
- **⚡ 开机**:启动VPS
|
||||||
- **🔴 关机**:关闭VPS
|
- **🔴 关机**:关闭VPS
|
||||||
- **🔄 硬重启**:强制重启VPS
|
- **🔄 硬重启**:强制重启VPS
|
||||||
@ -225,6 +236,7 @@ API密钥: your_api_key
|
|||||||
#### 刷新VPS列表
|
#### 刷新VPS列表
|
||||||
|
|
||||||
点击顶部工具栏的 "🔄 手动刷新VPS列表" 按钮:
|
点击顶部工具栏的 "🔄 手动刷新VPS列表" 按钮:
|
||||||
|
|
||||||
1. 从API获取最新的VPS列表
|
1. 从API获取最新的VPS列表
|
||||||
2. 更新数据库中的VPS信息
|
2. 更新数据库中的VPS信息
|
||||||
3. 获取每个VPS的详细配置(CPU、内存、磁盘、带宽、系统)
|
3. 获取每个VPS的详细配置(CPU、内存、磁盘、带宽、系统)
|
||||||
@ -243,7 +255,6 @@ sudo systemctl start idc_monitor
|
|||||||
sudo systemctl status idc_monitor
|
sudo systemctl status idc_monitor
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### 停止监控
|
#### 停止监控
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -285,7 +296,7 @@ sudo systemctl restart idc_monitor
|
|||||||
### 数据库文件
|
### 数据库文件
|
||||||
|
|
||||||
| 文件名 | 用途 | 主要表 |
|
| 文件名 | 用途 | 主要表 |
|
||||||
|--------|------|--------|
|
| ------------ | ------------ | ---------------------------- |
|
||||||
| `vps.db` | 存储平台配置 | `configs` |
|
| `vps.db` | 存储平台配置 | `configs` |
|
||||||
| `vpslist.db` | 存储VPS列表 | `vps_list` |
|
| `vpslist.db` | 存储VPS列表 | `vps_list` |
|
||||||
| `status.db` | 存储监控记录 | `ping_status`, `vps_summary` |
|
| `status.db` | 存储监控记录 | `ping_status`, `vps_summary` |
|
||||||
@ -421,7 +432,8 @@ WantedBy=multi-user.target
|
|||||||
|
|
||||||
### 访问控制
|
### 访问控制
|
||||||
|
|
||||||
- **API密码保护**:所有页面都需要通过 `?pass=API_PASS` 验证
|
- **会话密码保护**:所有页面通过前端输入访问密码(POST 方式)验证,验证成功后建立 PHP 会话
|
||||||
|
- **会话有效期**:单次会话 30 分钟,用户请求新数据后自动刷新会话有效期(滑动过期)
|
||||||
- **密码文件**:存储在 `app/pass.php`,权限设置为 600
|
- **密码文件**:存储在 `app/pass.php`,权限设置为 600
|
||||||
- **数据库保护**:Nginx配置禁止直接访问 `.db` 文件,或者限制访问app路径需要basic认证
|
- **数据库保护**:Nginx配置禁止直接访问 `.db` 文件,或者限制访问app路径需要basic认证
|
||||||
|
|
||||||
@ -446,6 +458,7 @@ WantedBy=multi-user.target
|
|||||||
### Q1: 页面显示"0台VPS"怎么办?
|
### Q1: 页面显示"0台VPS"怎么办?
|
||||||
|
|
||||||
**A**:
|
**A**:
|
||||||
|
|
||||||
1. 点击"手动刷新VPS列表"按钮
|
1. 点击"手动刷新VPS列表"按钮
|
||||||
2. 检查配置是否正确(特别是site_url不要包含路径)
|
2. 检查配置是否正确(特别是site_url不要包含路径)
|
||||||
3. 查看PHP错误日志:`tail -f /var/log/php/error.log`
|
3. 查看PHP错误日志:`tail -f /var/log/php/error.log`
|
||||||
@ -455,6 +468,7 @@ WantedBy=multi-user.target
|
|||||||
### Q2: 监控服务无法启动?
|
### Q2: 监控服务无法启动?
|
||||||
|
|
||||||
**A**:
|
**A**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 检查服务状态
|
# 检查服务状态
|
||||||
sudo systemctl status idc_monitor
|
sudo systemctl status idc_monitor
|
||||||
@ -474,6 +488,7 @@ journalctl -u idc_monitor -n 50
|
|||||||
|
|
||||||
**A**:
|
**A**:
|
||||||
系统已经做了兼容处理:
|
系统已经做了兼容处理:
|
||||||
|
|
||||||
- 如果exec被禁用,会显示友好提示
|
- 如果exec被禁用,会显示友好提示
|
||||||
- 需要手动执行安装脚本:`sudo bash app/install.sh`
|
- 需要手动执行安装脚本:`sudo bash app/install.sh`
|
||||||
- 监控服务仍然可以正常运行
|
- 监控服务仍然可以正常运行
|
||||||
@ -484,11 +499,13 @@ journalctl -u idc_monitor -n 50
|
|||||||
|
|
||||||
**A**:
|
**A**:
|
||||||
可能原因:
|
可能原因:
|
||||||
|
|
||||||
1. 数据库中还没有该VPS的记录
|
1. 数据库中还没有该VPS的记录
|
||||||
2. 多次调用导致状态被覆盖(已修复)
|
2. 多次调用导致状态被覆盖(已修复)
|
||||||
3. API返回异常
|
3. API返回异常
|
||||||
|
|
||||||
解决方法:
|
解决方法:
|
||||||
|
|
||||||
- 手动刷新VPS列表
|
- 手动刷新VPS列表
|
||||||
- 检查日志确认API调用是否正常
|
- 检查日志确认API调用是否正常
|
||||||
- 等待下一次监控循环
|
- 等待下一次监控循环
|
||||||
@ -498,12 +515,14 @@ journalctl -u idc_monitor -n 50
|
|||||||
### Q5: 如何添加新的VPS平台?
|
### Q5: 如何添加新的VPS平台?
|
||||||
|
|
||||||
**A**:
|
**A**:
|
||||||
|
|
||||||
1. 在 `app/monitor.py` 中创建新的适配器类
|
1. 在 `app/monitor.py` 中创建新的适配器类
|
||||||
2. 继承 `PlatformAdapter` 基类
|
2. 继承 `PlatformAdapter` 基类
|
||||||
3. 实现必要的方法(login, get_vps_list, get_vps_status等)
|
3. 实现必要的方法(login, get_vps_list, get_vps_status等)
|
||||||
4. 在 `load_configs_and_create_adapters()` 中添加判断逻辑
|
4. 在 `load_configs_and_create_adapters()` 中添加判断逻辑
|
||||||
|
|
||||||
示例:
|
示例:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
class AliyunAdapter(PlatformAdapter):
|
class AliyunAdapter(PlatformAdapter):
|
||||||
def login(self):
|
def login(self):
|
||||||
@ -520,11 +539,13 @@ class AliyunAdapter(PlatformAdapter):
|
|||||||
### Q6: 数据库文件在哪里?
|
### Q6: 数据库文件在哪里?
|
||||||
|
|
||||||
**A**:
|
**A**:
|
||||||
|
|
||||||
- `app/db/vps.db` - 配置数据库
|
- `app/db/vps.db` - 配置数据库
|
||||||
- `app/db/vpslist.db` - VPS列表数据库
|
- `app/db/vpslist.db` - VPS列表数据库
|
||||||
- `app/db/status.db` - 监控状态数据库
|
- `app/db/status.db` - 监控状态数据库
|
||||||
|
|
||||||
可以使用SQLite工具查看:
|
可以使用SQLite工具查看:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sqlite3 app/db/vpslist.db
|
sqlite3 app/db/vpslist.db
|
||||||
.tables
|
.tables
|
||||||
@ -536,6 +557,7 @@ SELECT * FROM vps_list;
|
|||||||
### Q7: 如何备份数据?
|
### Q7: 如何备份数据?
|
||||||
|
|
||||||
**A**:
|
**A**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 备份所有数据库
|
# 备份所有数据库
|
||||||
cp app/db/*.db backup/$(date +%Y%m%d)/
|
cp app/db/*.db backup/$(date +%Y%m%d)/
|
||||||
@ -552,7 +574,6 @@ sqlite3 app/db/vpslist.db ".dump" > backup/vpslist.sql
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
## 📧 联系方式
|
## 📧 联系方式
|
||||||
|
|
||||||
- **项目地址**: [https://git.masonliu.com/MasonLiu/VPSHUB](https://git.masonliu.com/MasonLiu/VPSHUB)
|
- **项目地址**: [https://git.masonliu.com/MasonLiu/VPSHUB](https://git.masonliu.com/MasonLiu/VPSHUB)
|
||||||
@ -564,6 +585,7 @@ sqlite3 app/db/vpslist.db ".dump" > backup/vpslist.sql
|
|||||||
## 🙏 致谢
|
## 🙏 致谢
|
||||||
|
|
||||||
感谢以下开源项目:
|
感谢以下开源项目:
|
||||||
|
|
||||||
- [PHP](https://www.php.net/)
|
- [PHP](https://www.php.net/)
|
||||||
- [Python](https://www.python.org/)
|
- [Python](https://www.python.org/)
|
||||||
- [SQLite](https://www.sqlite.org/)
|
- [SQLite](https://www.sqlite.org/)
|
||||||
|
|||||||
175
app/auth.php
Normal file
175
app/auth.php
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* VPS Hub 统一会话认证模块
|
||||||
|
*
|
||||||
|
* 功能:
|
||||||
|
* - 前端输入访问密码(POST)验证后建立 PHP 会话
|
||||||
|
* - 单次会话有效期 30 分钟(滑动过期)
|
||||||
|
* - 用户每次发起有效请求后自动刷新会话有效期
|
||||||
|
*
|
||||||
|
* 用法:
|
||||||
|
* require_once __DIR__ . '/app/auth.php';
|
||||||
|
* requireAuth(); // 未登录则展示登录页并终止脚本
|
||||||
|
* isLoggedIn(); // 返回当前会话是否有效
|
||||||
|
* attemptLogin($password); // 验证密码并建立会话
|
||||||
|
* logout(); // 手动退出登录
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 会话有效期:30 分钟(秒)
|
||||||
|
if (!defined('SESSION_LIFETIME')) {
|
||||||
|
define('SESSION_LIFETIME', 1800);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 会话垃圾回收最大存活时间(需在 session_start 之前设置)
|
||||||
|
ini_set('session.gc_maxlifetime', SESSION_LIFETIME);
|
||||||
|
|
||||||
|
// 启动会话
|
||||||
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断当前会话是否已通过认证
|
||||||
|
* 已登录且未超过 30 分钟无操作时,刷新会话有效期(滑动过期)
|
||||||
|
*
|
||||||
|
* @return bool 是否有效登录态
|
||||||
|
*/
|
||||||
|
function isLoggedIn() {
|
||||||
|
if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 滑动过期判断:超过 30 分钟无任何请求则会话失效
|
||||||
|
if (!isset($_SESSION['last_activity']) || (time() - intval($_SESSION['last_activity'])) > SESSION_LIFETIME) {
|
||||||
|
// 销毁过期会话
|
||||||
|
$_SESSION = [];
|
||||||
|
if (ini_get('session.use_cookies')) {
|
||||||
|
$params = session_get_cookie_params();
|
||||||
|
setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
|
||||||
|
}
|
||||||
|
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||||
|
session_destroy();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户请求了新数据,刷新会话有效期
|
||||||
|
$_SESSION['last_activity'] = time();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证访问密码并建立登录会话
|
||||||
|
* 使用 hash_equals 进行时序安全比对,防止时序攻击
|
||||||
|
*
|
||||||
|
* @param string $password 用户提交的访问密码
|
||||||
|
* @return bool 是否登录成功
|
||||||
|
*/
|
||||||
|
function attemptLogin($password) {
|
||||||
|
if (!defined('API_PASS')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash_equals(API_PASS, (string)$password)) {
|
||||||
|
// 会话固定攻击防护:重新生成会话ID
|
||||||
|
session_regenerate_id(true);
|
||||||
|
$_SESSION['admin_logged_in'] = true;
|
||||||
|
$_SESSION['last_activity'] = time();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强制要求登录认证
|
||||||
|
* 未认证时输出登录页面并终止当前脚本
|
||||||
|
* 已认证时直接返回,不影响后续流程
|
||||||
|
*
|
||||||
|
* @param string $redirect 登录成功后跳转的站内地址(可选,默认回到当前页面)
|
||||||
|
*/
|
||||||
|
function requireAuth($redirect = '') {
|
||||||
|
if (isLoggedIn()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理登录表单提交(POST 携带 auth_password)
|
||||||
|
$error = '';
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['auth_password'])) {
|
||||||
|
if (attemptLogin($_POST['auth_password'])) {
|
||||||
|
// 登录成功,跳转回目标页面
|
||||||
|
$target = !empty($_POST['redirect']) ? trim($_POST['redirect']) : $redirect;
|
||||||
|
// 仅允许站内跳转,防止开放重定向
|
||||||
|
if ($target && strpos($target, '://') === false && strpos($target, '\\') === false) {
|
||||||
|
header('Location: ' . $target);
|
||||||
|
} else {
|
||||||
|
header('Location: ' . $_SERVER['PHP_SELF']);
|
||||||
|
}
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$error = '访问密码错误,请重试!';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造登录成功后返回的地址(默认当前请求地址)
|
||||||
|
$currentPage = $_SERVER['PHP_SELF'];
|
||||||
|
$queryString = $_SERVER['QUERY_STRING'] ?? '';
|
||||||
|
$redirectTarget = !empty($redirect)
|
||||||
|
? $redirect
|
||||||
|
: ($queryString ? $currentPage . '?' . $queryString : $currentPage);
|
||||||
|
|
||||||
|
// 输出登录页面
|
||||||
|
header('Content-Type: text/html; charset=utf-8');
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="shortcut icon" href="./static/favicon.ico" type="image/x-icon">
|
||||||
|
<link href="./static/initial.css" rel="stylesheet" type="text/css">
|
||||||
|
<title>访问验证 - VPS Hub</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="config-container">
|
||||||
|
<div class="config-header">
|
||||||
|
<h1>🔐 VPS Hub</h1>
|
||||||
|
<p>请输入访问密码以进入管理面板</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="error-message">❌ <?php echo htmlspecialchars($error); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<form method="POST" action="<?php echo htmlspecialchars($currentPage); ?>">
|
||||||
|
<input type="hidden" name="redirect" value="<?php echo htmlspecialchars($redirectTarget); ?>">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="auth_password">访问密码</label>
|
||||||
|
<input type="password" id="auth_password" name="auth_password" required
|
||||||
|
placeholder="请输入访问密码" autofocus autocomplete="current-password">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn-submit">🔓 登录</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="info-box" style="margin-top: 20px;">
|
||||||
|
💡 登录会话有效期 30 分钟,期间操作会自动续期;超过 30 分钟无操作需重新登录。
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
<?php
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出登录并销毁会话
|
||||||
|
*/
|
||||||
|
function logout() {
|
||||||
|
$_SESSION = [];
|
||||||
|
if (ini_get('session.use_cookies')) {
|
||||||
|
$params = session_get_cookie_params();
|
||||||
|
setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
|
||||||
|
}
|
||||||
|
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||||
|
session_destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
require_once __DIR__ . '/app/db_helper.php';
|
require_once __DIR__ . '/app/db_helper.php';
|
||||||
|
require_once __DIR__ . '/app/auth.php';
|
||||||
require_once __DIR__ . '/mofangidc.php';
|
require_once __DIR__ . '/mofangidc.php';
|
||||||
|
|
||||||
// Token文件路径(存储API_PASS)
|
// Token文件路径(存储API_PASS)
|
||||||
@ -33,7 +34,10 @@ if ($needSetup && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['setup_p
|
|||||||
|
|
||||||
if (file_put_contents($tokenFile, $content)) {
|
if (file_put_contents($tokenFile, $content)) {
|
||||||
chmod($tokenFile, 0600);
|
chmod($tokenFile, 0600);
|
||||||
header('Location: config_add.php?pass=' . urlencode($apiPass));
|
// 密码刚由本人设置,直接建立登录会话并跳转
|
||||||
|
include $tokenFile;
|
||||||
|
attemptLogin($apiPass);
|
||||||
|
header('Location: config_add.php');
|
||||||
exit;
|
exit;
|
||||||
} else {
|
} else {
|
||||||
$setupError = '保存失败,请检查目录权限!';
|
$setupError = '保存失败,请检查目录权限!';
|
||||||
@ -114,14 +118,8 @@ if (file_exists($tokenFile)) {
|
|||||||
include $tokenFile;
|
include $tokenFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证pass参数
|
// 会话认证:前端输入密码验证后建立会话,30分钟滑动过期
|
||||||
$pass = isset($_GET['pass']) ? $_GET['pass'] : '';
|
requireAuth();
|
||||||
|
|
||||||
if (!defined('API_PASS') || $pass !== API_PASS) {
|
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
|
||||||
echo json_encode(['status' => 403, 'msg' => '访问密码错误'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理添加配置
|
// 处理添加配置
|
||||||
$message = '';
|
$message = '';
|
||||||
@ -383,7 +381,10 @@ $configs = $db->query('SELECT * FROM configs ORDER BY id');
|
|||||||
<div class="header">
|
<div class="header">
|
||||||
<h1>⚙️ VPS配置管理</h1>
|
<h1>⚙️ VPS配置管理</h1>
|
||||||
<p>添加和管理多平台VPS配置</p>
|
<p>添加和管理多平台VPS配置</p>
|
||||||
<a href="index.php?pass=<?php echo urlencode($pass); ?>" class="btn" style="float: right; margin-top: -60px;">返回首页</a>
|
<div style="float: right; margin-top: -60px; display: flex; gap: 10px; align-items: center;">
|
||||||
|
<a href="index.php" class="btn">返回首页</a>
|
||||||
|
<a href="index.php?logout=1" class="btn" style="background: #6c757d; color: white;" onclick="return confirm('确认退出登录?')">🚪 退出登录</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
|||||||
32
index.php
32
index.php
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/app/db_helper.php';
|
require_once __DIR__ . '/app/db_helper.php';
|
||||||
require_once __DIR__ . '/app/logger.php';
|
require_once __DIR__ . '/app/logger.php';
|
||||||
|
require_once __DIR__ . '/app/auth.php';
|
||||||
require_once __DIR__ . '/mofangidc.php';
|
require_once __DIR__ . '/mofangidc.php';
|
||||||
require_once __DIR__ . '/tencentcloud.php';
|
require_once __DIR__ . '/tencentcloud.php';
|
||||||
require_once __DIR__ . '/aliyun.php';
|
require_once __DIR__ . '/aliyun.php';
|
||||||
@ -17,15 +18,16 @@ if (!file_exists($tokenFile)) {
|
|||||||
// 加载API_PASS
|
// 加载API_PASS
|
||||||
include $tokenFile;
|
include $tokenFile;
|
||||||
|
|
||||||
// 验证pass参数
|
// 处理退出登录(需在会话认证之前,保证已登录用户也能退出)
|
||||||
$pass = isset($_GET['pass']) ? $_GET['pass'] : '';
|
if (isset($_GET['logout'])) {
|
||||||
|
logout();
|
||||||
if (!defined('API_PASS') || $pass !== API_PASS) {
|
header('Location: ' . $_SERVER['PHP_SELF']);
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
|
||||||
echo json_encode(['status' => 403, 'msg' => '访问密码错误或者未输入密码,请拼接?pass=API_PASS后再尝试访问'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 会话认证:前端输入密码验证后建立会话,30分钟滑动过期
|
||||||
|
requireAuth();
|
||||||
|
|
||||||
// 处理操作请求
|
// 处理操作请求
|
||||||
$message = '';
|
$message = '';
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
@ -295,6 +297,15 @@ foreach ($vpsList as $vps) {
|
|||||||
.btn-refresh:hover {
|
.btn-refresh:hover {
|
||||||
background-color: #0056b3;
|
background-color: #0056b3;
|
||||||
}
|
}
|
||||||
|
.btn-logout {
|
||||||
|
background-color: #6c757d;
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.btn-logout:hover {
|
||||||
|
background-color: #5a6268;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
.config-title {
|
.config-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@ -478,9 +489,14 @@ foreach ($vpsList as $vps) {
|
|||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<a href="config_add.php?pass=<?php echo urlencode($pass); ?>" class="btn btn-success">
|
<div style="display: flex; gap: 10px; align-items: center;">
|
||||||
|
<a href="config_add.php" class="btn btn-success">
|
||||||
➕ 添加配置源
|
➕ 添加配置源
|
||||||
</a>
|
</a>
|
||||||
|
<a href="index.php?logout=1" class="btn btn-logout" onclick="return confirm('确认退出登录?')">
|
||||||
|
🚪 退出登录
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 统计信息 -->
|
<!-- 统计信息 -->
|
||||||
@ -500,7 +516,7 @@ foreach ($vpsList as $vps) {
|
|||||||
<div class="empty-state">
|
<div class="empty-state">
|
||||||
<h3>📭 暂无配置</h3>
|
<h3>📭 暂无配置</h3>
|
||||||
<p>请先添加VPS配置才能开始管理</p>
|
<p>请先添加VPS配置才能开始管理</p>
|
||||||
<a href="config_add.php?pass=<?php echo urlencode($pass); ?>" class="btn btn-success" style="margin-top: 20px;">
|
<a href="config_add.php" class="btn btn-success" style="margin-top: 20px;">
|
||||||
➕ 添加第一个配置
|
➕ 添加第一个配置
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
54
view_log.php
54
view_log.php
@ -1,54 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/app/logger.php';
|
require_once __DIR__ . '/app/logger.php';
|
||||||
require_once __DIR__ . '/app/pass.php';
|
require_once __DIR__ . '/app/auth.php';
|
||||||
|
|
||||||
// 检查是否已登录(简单验证)
|
// 加载API_PASS(未设置则跳转到配置页)
|
||||||
session_start();
|
if (!file_exists(__DIR__ . '/app/pass.php')) {
|
||||||
if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true) {
|
header('Location: config_add.php');
|
||||||
// 如果没有登录,显示简单的密码验证
|
|
||||||
if (isset($_POST['password'])) {
|
|
||||||
// 使用pass.php中定义的API_PASS作为密码
|
|
||||||
if ($_POST['password'] === API_PASS) {
|
|
||||||
$_SESSION['admin_logged_in'] = true;
|
|
||||||
} else {
|
|
||||||
$error = '密码错误';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($_SESSION['admin_logged_in'])) {
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>VPSHUB - 日志查看</title>
|
|
||||||
<style>
|
|
||||||
body { font-family: Arial, sans-serif; margin: 50px; background: #f5f5f5; }
|
|
||||||
.login-box { max-width: 400px; margin: 100px auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
|
|
||||||
h2 { margin-top: 0; color: #333; }
|
|
||||||
input[type="password"] { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; }
|
|
||||||
button { width: 100%; padding: 10px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; }
|
|
||||||
button:hover { background: #0056b3; }
|
|
||||||
.error { color: red; margin-bottom: 10px; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="login-box">
|
|
||||||
<h2>🔐 日志查看权限验证</h2>
|
|
||||||
<?php if (isset($error)): ?>
|
|
||||||
<div class="error"><?php echo htmlspecialchars($error); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<form method="POST">
|
|
||||||
<input type="password" name="password" placeholder="请输入管理员密码" required>
|
|
||||||
<button type="submit">登录</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
<?php
|
|
||||||
exit;
|
exit;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
include __DIR__ . '/app/pass.php';
|
||||||
|
|
||||||
|
// 统一会话认证:前端输入密码验证后建立会话,30分钟滑动过期
|
||||||
|
requireAuth();
|
||||||
|
|
||||||
// 处理操作
|
// 处理操作
|
||||||
$action = $_GET['action'] ?? '';
|
$action = $_GET['action'] ?? '';
|
||||||
|
|||||||
5
新开发文档.md
5
新开发文档.md
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
初次访问该php页面时,用户需设置网页自定义访问密码:API_PASS(运行输入大小写字母以及数字,最低8位数)
|
初次访问该php页面时,用户需设置网页自定义访问密码:API_PASS(运行输入大小写字母以及数字,最低8位数)
|
||||||
|
|
||||||
存在API_PASS时,需跟参数?pass=API_PASS才允许访问
|
存在API_PASS时,访问需先在前端输入访问密码(POST方式验证),验证成功后建立PHP会话,会话有效期30分钟(滑动过期,用户请求新数据后自动续期)
|
||||||
|
|
||||||
用户点击添加配置按钮,新列出一列,分别是:
|
用户点击添加配置按钮,新列出一列,分别是:
|
||||||
旧数据也会读取并展示
|
旧数据也会读取并展示
|
||||||
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#### 首页 index.php
|
#### 首页 index.php
|
||||||
|
|
||||||
1. 查询是否存在API_PASS,若存在,则需跟参数?pass=API_PASS才能访问
|
1. 查询是否存在API_PASS,若存在,访问时需先输入访问密码(POST方式验证)建立PHP会话,会话有效期30分钟(滑动过期)
|
||||||
|
|
||||||
2. 若不存在,则跳转至config_add.php页
|
2. 若不存在,则跳转至config_add.php页
|
||||||
|
|
||||||
@ -66,4 +66,3 @@
|
|||||||
(获取到的认证token存储于./app/token.php中,记录为两小时)
|
(获取到的认证token存储于./app/token.php中,记录为两小时)
|
||||||
|
|
||||||
3. 若section为True,且ping测试失败,调用API对该机器进行状态查询,若返回状态为关机,则尝试开机,隔60秒后再进行状态查询并再次尝试开机,60秒后查询还是为异常的话,则记录异常,进入下一个循环(多台机器关机时,依次进行状态查询和开机,然后间隔60秒再进行操作,不同的机器不需要间隔)
|
3. 若section为True,且ping测试失败,调用API对该机器进行状态查询,若返回状态为关机,则尝试开机,隔60秒后再进行状态查询并再次尝试开机,60秒后查询还是为异常的话,则记录异常,进入下一个循环(多台机器关机时,依次进行状态查询和开机,然后间隔60秒再进行操作,不同的机器不需要间隔)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user