PHP 配置文件敏感信息加密保护实践
在 PHP 应用开发中,数据库密码、API 密钥、JWT 秘钥等敏感信息常存于 .env 或 config.php 文件中。若配置文件意外泄露(如 Git 提交、Web 目录误暴露),将导致严重安全风险。本文介绍一种轻量、可靠且符合 PSR 标准的加密保护方案。
核心思路:运行时解密,源码零明文
不将明文密钥写入版本库,而是使用对称加密(AES-256-CBC)加密敏感字段,并将密文与加密密钥(ENCRYPTION_KEY)分离存储——密钥仅存在于服务器环境变量或安全密钥管理服务中。
示例:加密配置与解密加载
步骤 1:生成安全密钥(一次执行)
// generate-key.php
$key = random_bytes(32); // 256-bit key
echo "ENCRYPTION_KEY=" . bin2hex($key) . "\n";
步骤 2:加密敏感值(本地执行)
// encrypt-value.php
$encryptionKey = hex2bin('your_32_byte_hex_key_here'); // 来自 ENCRYPTION_KEY
$value = 'my-db-password-123';
$iv = random_bytes(16);
$ciphertext = openssl_encrypt($value, 'AES-256-CBC', $encryptionKey, 0, $iv);
$encrypted = base64_encode($iv . $ciphertext);
echo "DB_PASSWORD_ENCRYPTED={$encrypted}\n"; // 存入 .env
步骤 3:运行时安全解密(推荐封装为 ConfigLoader 类)
<?php
// src/ConfigLoader.php
class ConfigLoader
{
private static ?array $cache = null;
public static function get(string $key, ?string $default = null): ?string
{
if (self::$cache === null) {
self::$cache = self::loadAndDecrypt();
}
return self::$cache[$key] ?? $default;
}
private static function loadAndDecrypt(): array
{
$env = parse_ini_file(__DIR__ . '/../.env', true) ?: [];
$key = hex2bin($_SERVER['ENCRYPTION_KEY'] ?? '');
if (!$key || strlen($key) !== 32) {
throw new RuntimeException('Invalid or missing ENCRYPTION_KEY');
}
$decrypted = [];
foreach ($env as $k => $v) {
if (str_ends_with($k, '_ENCRYPTED') && is_string($v)) {
$raw = base64_decode($v);
$iv = substr($raw, 0, 16);
$ciphertext = substr($raw, 16);
$plaintext = openssl_decrypt($ciphertext, 'AES-256-CBC', $key, 0, $iv);
$decrypted[str_replace('_ENCRYPTED', '', $k)] = $plaintext ?: null;
} else {
$decrypted[$k] = $v;
}
}
return $decrypted;
}
}
// 使用示例:
// $dbPassword = ConfigLoader::get('DB_PASSWORD');
⚠️ 安全提示:务必通过
php.ini 禁用 display_errors;将 .env 加入 .gitignore;生产环境通过 export ENCRYPTION_KEY=... 设置环境变量,切勿硬编码。
该方案兼顾安全性与可维护性:密钥与密文物理隔离,解密逻辑集中可控,且无需引入外部依赖。配合 Composer 自动加载与 PSR-4 规范,可无缝集成至 Laravel、Symfony 或原生项目中。
记住:加密不是万能盾牌,但它是纵深防御中不可或缺的一环——让攻击者即使拿到配置文件,也仍需突破密钥这道最后关卡。
```