ThinkPHP本身不提供PHP源文件加密能力,仅支持敏感数据运行时解密、接口传输加解密、Cookie自动加密三类安全实践;需严格区分配置项解密(如database.php调用自定义Security::decrypt)、API响应/请求加解密(AES-128-CBC+base64)、Cookie签名或加密(Crypt::encrypt+sign),禁用md5/base64伪装加密及第三方代码混淆。

ThinkPHP 本身不提供对 PHP 源文件(如控制器、模型、配置文件)的加密能力,所谓“ThinkPHP 文件加密”,实际是指两类常见需求:
- 对敏感数据(如数据库密码、API密钥)在配置中做运行时解密
- 对传输内容(如 API 返回、前端参数、Cookie)做加解密处理
直接加密 .php 文件(比如用 Zend Guard 或 Swoole Compiler)属于 PHP 层面的代码混淆/保护,与 ThinkPHP 框架无关,且不推荐用于安全防护——它防不了有权限的运维人员,也增加调试和升级成本。
下面分场景说清楚怎么做、为什么这么选:
一、数据库密码等配置项加密(运行时解密)
不能把明文密码写在 config/database.php 或 .env 里。正确做法是:
立即学习“PHP免费学习笔记(深入)”;
- 用外部工具(如 OpenSSL、KMS 或自研脚本)将数据库密码加密成密文,存为环境变量,例如:
DB_PASSWORD_CIPHER=U2FsdGVkX1+abc123... - 在
config/database.php中调用自定义解密类:'password' => \app\common\Security::decrypt(getenv('DB_PASSWORD_CIPHER')) - 解密类必须满足:密钥不硬编码、IV 随机生成并随密文存储、失败立即抛异常;禁用
think\facade\Crypt(它初始化太晚,database.php 加载时不可用)
二、接口响应/请求参数加密(前后端约定加解密)
适用于需要防止中间人窥探返回内容(如订单详情、用户信息)的场景:
- 服务端统一在
app\common\behavior\ResponseEncrypt.php行为中处理响应体:
先json_encode→ AES-128-CBC 加密 → base64 编码 → 写入响应 - 密钥和 IV 必须固定(如从
getenv('API_ENC_KEY')和getenv('API_ENC_IV')读取),不能每次随机,否则前端无法解 - 前端拿到密文后,用相同算法 + 相同密钥/IV 解密;注意:IV 长度必须为 16 字节(AES-CBC 要求)
- 避免用
time()等动态值参与密钥生成——会导致前后端不同步
三、Cookie 登录凭证加密(替代 Session)
若想用 Cookie 存用户 ID、过期时间等轻量信息,需保证不可篡改:
- 不要自己手写 XOR 或简单替换算法(易被逆向)
- 推荐用 ThinkPHP 自带的
think\facade\Cookie+ 签名机制:Cookie::set('user_token', $data, ['sign' => true]),框架会自动用app.cookie_salt签名 - 如需加密内容(不只是签名),可组合使用:
Cookie::set('user_token', Crypt::encrypt(json_encode($payload)), [...]),但注意Crypt的密钥必须稳定、跨环境一致
四、别踩的坑
这些操作看似“加密”,实则无效甚至危险:
- 把
config/database.php里的密码用md5()或base64_encode()包一层——这不是加密,只是编码,毫无安全性 - 在控制器里用
Str::encrypt()处理参数再入库——该方法密钥派生不透明、无认证、不兼容跨环境,TP6 官方已不建议用于业务字段 - 试图加密整个
app/目录并部署——PHP 运行依赖源码解析,强行加密会导致 Fatal error 或白屏 - 用第三方混淆工具打包后声称“代码已加密”——只要能运行,就能被内存 dump 或 xdebug 反射还原逻辑
不复杂但容易忽略。核心就一条:加密是为了控制数据可见范围,不是给代码穿马甲。该在哪解,就在哪解;密钥谁管,谁负责轮换和审计。



















