TP5的common.php不能直接写openssl_encrypt()等函数,因其无自动加载、不支持命名空间,且裸调易致IV不一致、ECB误用、密钥长度错误等问题;应封装为Aes/Rsa类并在common.php中桥接调用,密钥须通过config()或环境变量注入,避免硬编码。

TP5 的函数文件本身不负责实现加密逻辑,它只负责暴露调用入口;真正做加密必须用 PHP 原生 openssl_* 函数或引入封装好的类(如 Aes、Rsa),否则会直接报错或返回空。
为什么不能在 common.php 里直接写 openssl_encrypt()
因为 common.php 是纯函数定义文件,没有自动加载机制,也不支持 namespace 或 use;而 openssl_encrypt() 等函数虽是原生的,但密钥、IV、模式等参数极易配错,裸写极易导致:
- 加密结果每次都不一致(比如用了随机 IV 却没保存)
- 解密时抛出 warning:「error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt」
- ECB 模式被误用于敏感数据(无 IV、不安全,但新手常默认选它)
- 传入的
$key长度不匹配算法要求(如 AES-256 要 32 字节,传了 16 字节字符串就静默失败)
正确做法:把加密逻辑封装成独立类,再在函数文件中桥接
例如在 extend/aes/Aes.php 写好类后,在 application/common.php 中只加一层薄封装:
if (!function_exists('aes_encrypt')) {
function aes_encrypt($data, $key = 'default_key') {
$aes = new \extend\aes\Aes($key, 'AES-128-CBC');
return $aes->encrypt($data);
}
}
if (!function_exists('aes_decrypt')) {
function aes_decrypt($data, $key = 'default_key') {
$aes = new \extend\aes\Aes($key, 'AES-128-CBC');
return $aes->decrypt($data);
}
}
这样既复用已有类,又能在控制器里直接写 aes_encrypt('hello'),符合 TP5 的函数调用习惯。
注意 config() 和环境变量的密钥注入方式
硬编码密钥(如 'secret123')绝对不可上生产。应通过配置或环境变量注入:
- 在
application/config.php加:'cipher_key' => env('CIPHER_KEY', 'dev-fallback-key') - 类构造时改用:
$this->secret_key = config('cipher_key'); - 确保
.env文件中设置了CIPHER_KEY=32_byte_long_random_string_here...(用bin/php -r "echo base64_encode(random_bytes(32));"生成) - 避免用
md5($string)当密钥——它只有 16 字节,且可预测
RSA 加密不能塞进 common.php 的根本原因
Rsa::publicEncrypt() 类依赖 PEM 格式密钥字符串(含 -----BEGIN PUBLIC KEY----- 换行和 Base64),而 common.php 无法可靠加载外部文件或读取配置中的多行字符串。一旦把 $private_key = config('web.private_parm') 放进函数体,config 返回的是 null 或截断文本,openssl_pkey_get_private() 就直接返回 false,后续所有操作静默失败。
真正可行路径只有一条:把密钥加载、资源初始化、加解密方法全部保留在类内部(如你知识库里的 lib\Rsa),common.php 仅作静态代理调用,例如:
if (!function_exists('rsa_private_encrypt')) {
function rsa_private_encrypt($data) {
return \lib\Rsa::privateRncrypt($data);
}
}
密钥内容必须通过 config() 从完整字符串(含换行符)读取,并确保配置项值在 config/web.php 中用 nowdoc 或双引号包裹,否则换行丢失 —— 这是最容易被忽略、调试成本最高的一环。

















