perf/security: V0.9.5-0.9.6 db_pending_upgrades 缓存 + config 凭据外置

- V0.9.5 (P3): db_pending_upgrades() 加 static 请求内缓存,同请求只算一次
- V0.9.6 (安全): config.php 移除明文密码,改从 gitignored 的 config.secret.php 或
  环境变量读取;新增 config.secret.php.example 模板;.gitignore 忽略 config/config.secret.php
  (修复 Webhook reset 反复覆盖明文凭据的隐患;服务器部署前需自建 config.secret.php)
This commit is contained in:
2026-08-09 00:34:54 +08:00
parent d5c1edefae
commit 6d3962574c
4 changed files with 38 additions and 7 deletions
+1
View File
@@ -3,6 +3,7 @@ storage/cache/
storage/data/
storage/logs/
storage/uploads/
config/config.secret.php
*.zip
_dbg_login.html
start_local.sh
+8 -3
View File
@@ -544,12 +544,15 @@ if (!function_exists('site_url')) {
*/
function db_pending_upgrades(): int
{
// V0.9.5:请求内缓存(一次请求内多次调用只算一次),避免每后台页重复 glob+md5_file+SELECT
static $cache = null;
if ($cache !== null) return $cache;
try {
if (\Core\Db::driver() !== 'mysql') return 0;
if (\Core\Db::driver() !== 'mysql') { $cache = 0; return 0; }
$dir = db_upgrade_dir();
if (!is_dir($dir)) return 0;
if (!is_dir($dir)) { $cache = 0; return 0; }
$files = glob($dir . '/*.sql') ?: [];
if (!$files) return 0;
if (!$files) { $cache = 0; return 0; }
\Core\Installer::ensureUpgradeLog();
$applied = \Core\Db::query("SELECT file, hash FROM db_upgrades")->fetchAll(\PDO::FETCH_KEY_PAIR);
$n = 0;
@@ -560,8 +563,10 @@ if (!function_exists('site_url')) {
$n++;
}
}
$cache = $n;
return $n;
} catch (\Throwable $e) {
$cache = 0;
return 0;
}
}
+20 -4
View File
@@ -1,8 +1,24 @@
<?php
/**
* 全局配置
* driver: 'file' 开箱即用(无需数据库);'mysql' 用于生产部署
* 全局配置(不含敏感凭据,可安全入库)
*
* 敏感凭据(数据库密码 / 后台密码)从以下优先级读取,避免明文写入仓库:
* 1) 同级 config.secret.phpgitignored,需服务器侧自建;git reset --hard 不会被清除,建一次即可)
* 2) 环境变量 COOLCOTH_DB_PASS / COOLCOTH_ADMIN_PASS
* 3) 本文件中的占位(为空 → 连接失败,仅作本地演示占位)
*
* 部署步骤(务必在下次 Webhook 部署前完成,否则 DB 连接 / 后台登录会失败):
* 在服务器 /www/wwwroot/coolcoth.com/config/ 下新建 config.secret.php,内容参考 config.secret.php.example
*/
$secret = [];
if (file_exists(__DIR__ . '/config.secret.php')) {
$secret = require __DIR__ . '/config.secret.php';
}
$secret = array_merge([
'db_pass' => '',
'admin_pass' => '',
], $secret);
return [
'app' => [
'name' => '酷冰甲 · 降温服',
@@ -17,7 +33,7 @@ return [
'port' => 3306,
'dbname' => 'coolcoth_comf',
'user' => 'coolcoth_comf',
'pass' => 'QDBKzY817hDhTiKk',
'pass' => $secret['db_pass'] ?: (getenv('COOLCOTH_DB_PASS') ?: ''),
'charset' => 'utf8mb4',
],
'file' => [
@@ -27,7 +43,7 @@ return [
// 后台登录账号(文件模式 / 首次安装)
'admin' => [
'username' => 'admin',
'password' => 'admin888',
'password' => $secret['admin_pass'] ?: (getenv('COOLCOTH_ADMIN_PASS') ?: ''),
// 本地规则红线:生产环境(mysql 模式)必须关闭配置文件兜底账号,禁用默认密码后门。
// 仅本地演示(file 模式)可临时置 true。远端已实测默认密码可登录,已置 false 封堵。
'allow_config_fallback' => false,
+9
View File
@@ -0,0 +1,9 @@
<?php
/**
* config.secret.php 模板(可入库,供复制参考)
* 复制为 config.secret.php 并填入真实凭据;config.secret.php 已被 .gitignore 忽略,不会入库。
*/
return [
'db_pass' => '在此填入数据库密码',
'admin_pass' => '在此填入后台密码(务必改为强口令,不要用 admin888',
];