thinkphp cookie 加密开关由 config/app.php 中 cookie.encrypt 配置项控制,默认 true;设为 false 会跳过 aes 加密,但不推荐,因明文 cookie 易被篡改。

Cookie 加密开关在哪配
ThinkPHP 默认对 cookie 数据启用 AES 加密,开关由配置项 cookie.encrypt 控制。设为 false 会跳过加密,但不推荐——明文 Cookie 在前端可被任意读取,敏感字段(如用户 ID、权限标识)极易被篡改。
实际项目中建议保持默认 true,并在 config/app.php 中确认:
'cookie' => [<br> 'encrypt' => true,<br> 'httponly' => true,<br> 'secure' => $_SERVER['HTTPS'] ?? false,<br>],
- 加密密钥来自
app.key配置,不是随便写的字符串,必须是 32 字节(如bin2hex(random_bytes(16))生成) - 换密钥后旧 Cookie 全部失效,无法解密,线上切勿随意改动
-
httponly必须开,否则 JS 可通过document.cookie窃取
setcookie() 和 Cookie::set() 的区别
直接调用 PHP 原生 setcookie() 绕过了 ThinkPHP 的加密逻辑,存进去的是纯明文;而 Cookie::set() 会走完整流程:序列化 → AES 加密 → base64 编码 → 设置 HTTP Header。
错误写法:
setcookie('user_id', 123, time()+3600); // 明文,无加密,不校验签名
正确写法:
use think\facade\Cookie;<br>Cookie::set('user_id', 123, 3600); // 自动加密 + 签名验证
- 如果传数组或对象,
Cookie::set()会先serialize(),再加密;反序列化在get()时完成 - 原生
setcookie()不校验签名,攻击者可伪造 Cookie 内容;Cookie::get()会先验签,失败直接返回null - 加密后的 Cookie 值长度明显变长(比如
123变成U2FsdGVkX1+...),这是正常现象
Cookie::get() 返回 null 的常见原因
不是数据丢了,大概率是解密或验签失败。ThinkPHP 对 Cookie 做了双重保护:AES 解密 + HMAC-SHA256 签名验证,任一环节出错都返回 null。
排查顺序:
- 检查
app.key是否和写入时一致(部署时环境变量覆盖导致 key 不同) - 确认
cookie.encrypt配置没被运行时修改(比如中间件里调了Cookie::setEncrypt(false)) - 浏览器抓包看 Cookie 值是否被手动篡改过(哪怕改一个字符,HMAC 校验就失败)
- 注意时区问题:如果服务器时间比客户端快很多,
Cookie::get()可能因过期提前拒绝读取(即使浏览器还没删掉)
敏感字段别塞进 Cookie
加密 ≠ 安全存储。Cookie 本质是客户端可控的存储介质,即使加密,仍面临重放、拖库、中间人等风险。ThinkPHP 的加密只防“明文窥探”,不防“拿走整个加密串去别的设备用”。
真正该放的只有无状态标识,例如:
-
token_id(关联服务端 session 或数据库 token 表) -
theme(UI 主题偏好) -
lang(语言选择)
绝对不要放:
<code>user_password_hash</code>、<code>admin_flag</code>、<code>balance</code> <p>这些必须查库或 Redis 实时校验,Cookie 只当钥匙,不当保险箱。</p> <p>加密 Cookie 的边界很窄:它只保证“传输过程中不被看懂”,不代表“可以放心存重要东西”。真要存敏感态,上 session + Redis + 过期清理,别贪方便往 Cookie 塞。</p>
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











