ThinkPHP 6.x 必须在config/app.php的'cookie'块中设auto_encrypt=>true并配32字节以上secret_key,且需配合httponly、secure及HMAC签名防篡改,缺一不可。

ThinkPHP 的 Cookie 加密不是靠「配对 key 就自动安全」,而是必须显式启用 auto_encrypt、配对强密钥、并配合 httponly + secure 才能防篡改。缺一不可,否则加密形同虚设。
如何在 config/app.php 中正确启用 Cookie 自动加密
ThinkPHP 6.x 的 Cookie 加密开关和密钥必须写在 config/app.php 的 'cookie' 配置块内,而不是全局 'app' 或其他位置。框架只认这里声明的 auto_encrypt 和 secret_key。
-
auto_encrypt必须设为true(布尔值,不能是字符串"true") -
secret_key必须是至少 32 字节的随机字符串,建议用bin2hex(random_bytes(32))生成,不要手写或复用 APP_KEY - 若未配置
secret_key,即使auto_encrypt => true,框架也会静默降级为不加密,且不报错 - 加密仅作用于通过
Cookie::set()或cookie()设置的值;直接调用 PHP 原生setcookie()不受控
为什么加密后仍可能被篡改?关键在签名缺失
ThinkPHP 默认的自动加密只做对称加解密,不带消息认证(HMAC)。攻击者可截获加密后的 Cookie 值,原样重放或拼接其他合法密文,服务器仍会解密成功——这不算“解密失败”,而是逻辑层面的伪造。
- 防篡改必须依赖完整性校验,即:加密后附加一个基于密钥和密文的 HMAC 签名
- ThinkPHP 原生不提供开箱即用的带签名加密,需自行封装或使用第三方类(如
think-encrypt扩展) - 若坚持原生方案,可在设置 Cookie 前手动计算:
$hmac = hash_hmac('sha256', $ciphertext, $secret_key),再拼成$ciphertext.'|'.$hmac - 读取时必须先分割、再验签、最后解密;任一环节失败就丢弃该 Cookie
加密密钥泄露或复用导致跨应用越权
同一个 secret_key 被多个 ThinkPHP 应用共用,等于把所有应用的 Cookie 解密能力交到同一把钥匙上。A 应用生成的加密 Cookie 可被 B 应用成功解密并误认为合法身份。
立即学习“PHP免费学习笔记(深入)”;
- 每个生产环境应用必须使用独立生成的
secret_key,严禁硬编码在 Git 仓库中 - 推荐将密钥存入环境变量(如
$_ENV['COOKIE_SECRET']),并在config/app.php中引用:'secret_key' => $_ENV['COOKIE_SECRET'] ?? '' - 若使用 Docker 或云平台,通过 secret 管理功能注入,而非写进配置文件
- 密钥轮换时,需兼容旧密钥解密存量 Cookie,但新写入必须用新密钥——ThinkPHP 不支持多密钥自动 fallback,得自己实现
真正防篡改不只看“有没有加密”,而要看“密文是否绑定来源+时效+签名”。ThinkPHP 的 auto_encrypt 是起点,不是终点;密钥管理、传输通道(HTTPS)、HttpOnly 属性、以及服务端二次校验(比如比对 IP/User-Agent 散列),一个都不能少。



















