数据库密码严禁硬编码,应通过环境变量(如getenv('DB_PASSWORD'))读取并确保.env文件不可被Web访问;ThinkPHP中需显式引用环境变量,避免database.php中写死凭据,且须在CI/CD中检查和过滤敏感信息。

数据库密码不能硬编码在 database.php 里
硬编码凭据等于把钥匙贴在门上。ThinkPHP 的 database.php 配置文件默认是 PHP 脚本,一旦 Web 目录权限配置不当或服务器出问题,可能被直接下载或解析失败后暴露源码——里面明文的 password 就全漏了。
- 用环境变量替代:把
DB_PASSWORD写进服务器的.env或系统级环境变量,然后在配置中用getenv('DB_PASSWORD')读取 - 确保
.env文件不在 Web 可访问路径下(比如放到项目根目录但禁止 Nginx/Apache 解析该路径) - 如果必须用
database.php,至少把密码字段设为'',并在部署时通过 CI/CD 注入,而不是提交到 Git
ThinkPHP 6+ 的 .env 加载顺序和覆盖逻辑
ThinkPHP 默认会加载 .env,但它只在应用初始化早期生效,且不会自动覆盖已写死在 database.php 中的值——也就是说,如果你在 database.php 里写了 'password' => '123',哪怕 .env 里有 DB_PASSWORD=abc,也不会生效。
- 必须在
database.php中显式引用环境变量:'password' => getenv('DB_PASSWORD') ?: '' -
.env文件本身不支持嵌套或表达式,DB_PORT=3306可以,但DB_HOST=localhost:${DB_PORT}不行 - 开发环境和生产环境要用不同
.env,别让测试库密码混进线上部署包
敏感配置项不要进 Git:用 .gitignore 拦住 .env 和 database.php 的凭据部分
很多人以为只 ignore .env 就安全了,结果 database.php 里还留着测试账号,一提交就全网公开。ThinkPHP 官方模板的 database.php 示例本身就带明文密码,极易被复制粘贴后遗忘清理。
- 在
.gitignore中加两行:.env和config/database.php(如果该文件含凭据) - 更稳妥的做法是把
database.php拆成两部分:公共配置(host、port、charset)放 Git,敏感字段(username、password)由部署脚本注入或从环境变量读 - CI 流水线里做一次
grep -q "password\|passwd" config/database.php && exit 1检查,防手抖
连接池和长连接场景下,凭据泄露风险更高
启用 deploy => true 或使用 Swoole/Workerman 时,数据库连接常驻内存,凭据一旦加载就长期存在进程堆里。这时候如果日志开了 debug、或者用了某些调试扩展(如 xdebug 的远程调试),变量 dump 可能意外打出 $config['password']。
立即学习“PHP免费学习笔记(深入)”;
- 连接建立后立刻 unset 敏感字段:
unset($config['password']),尤其在自定义连接管理器里 - 避免在异常上下文中打印完整配置数组,改用
array_diff_key($config, ['password' => ''])过滤后再 log - Swoole 环境下,
getenv()在子进程里可能失效,建议启动时一次性读入全局常量,而非每次连接都调用
凭据隔离不是“配完就完事”,它依赖加载时机、变量生命周期和运行时上下文——哪一环松动,整条链就可能崩。


















