默认PHP文件会话不安全,因session数据明文存于临时目录且无加密签名,易被读取或篡改;应禁用files、启用Redis并严格配置use_strict_mode、cookie_httponly、cookie_secure等参数。

为什么默认的 PHP 文件会话不安全
ThinkPHP 默认用 session.save_handler = files,会话数据直接写进服务器临时目录,权限若没设好(比如 web 进程可遍历 /tmp),攻击者可能读取或伪造 PHPSESSID 对应的 session 文件。更麻烦的是,原生文件存储不加密、无签名,改个 user_id 字段就能越权登录。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 绝不要在生产环境保留
session.save_handler = files,尤其当服务器共用或托管在低权限环境时 - 即使换 Redis,也必须开启
session.use_strict_mode = 1(防会话固定)和session.cookie_httponly = 1 - ThinkPHP 的
session.encrypt配置仅对「写入前序列化内容」做 AES 加密,它不替代 Cookie 签名,也不防重放——得靠session.id_length+session.use_strict_mode组合兜底
如何正确配置 ThinkPHP 使用 Redis 存储会话
不是简单把 type 改成 redis 就完事。ThinkPHP 的 session 配置和底层 phpredis 扩展行为有隐含耦合,配错会导致连接失败、数据乱码或静默降级回 file。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 确认已安装
phpredis扩展(非predis),运行php -m | grep redis验证 -
session.type = redis必须搭配session.redis.host、session.redis.port,且session.redis.password为空时不能省略,要显式设为null或空字符串 - Redis 库号别用
0:ThinkPHP 会把所有会话 key 写进同一 DB,易被FLUSHDB清空,建议固定用session.redis.database = 2 - 务必设置
session.redis.timeout = 60(单位秒),否则超时连接卡住,后续请求全挂
Session ID 加密与 Cookie 安全参数必须手动补全
ThinkPHP 的 session.encrypt 只加密 session 数据体,但 Cookie 本身仍明文传输 ID。如果没关掉 session.cookie_secure 和 session.cookie_samesite,中间人能劫持并复用会话。
使用 Playwright 为 jimeng.jianying.com 管理浏览器会话,导入 cookies/localStorage 以自动化视频生成工作流,支持图片上传等功能
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- HTTPS 环境下,强制开启
session.cookie_secure = 1,否则浏览器拒绝发送带Secure标志的 Cookie -
session.cookie_samesite = Strict或Lax(推荐Lax),防止 CSRF;注意老版 IE 不支持SameSite=None,设成None反而失效 -
session.use_trans_sid = 0必须关闭,否则 URL 里暴露PHPSESSID,加密毫无意义 - 密钥长度要够:ThinkPHP 要求
session.encrypt_key至少 32 字节,用openssl_random_pseudo_bytes(32)生成,别手敲短密码
Redis 会话过期时间与 GC 机制冲突怎么办
PHP 原生会话 GC 概率由 session.gc_probability 控制,但 Redis 不走 PHP GC 流程。ThinkPHP 若没显式调用 gc(),过期会话会一直占内存,直到 Redis 自动淘汰(依赖 maxmemory-policy)。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 关闭 PHP 原生 GC:
session.gc_probability = 0,避免无谓的filemtime()扫描 - 在 Redis 配置中启用
maxmemory-policy volatile-lru,并确保所有会话 key 都带 TTL(ThinkPHP 默认写入时用SETEX,没问题) - 检查
session.expire是否小于 Redis 的timeout值,否则连接断开前会话就丢了——例如设session.expire = 7200,但 Redistimeout = 30,那 30 秒没操作连接就断,会话实际活不到 2 小时
最常被忽略的一点:Redis 密码含特殊字符(如 @、/)时,ThinkPHP 的 redis:// DSN 解析会出错,必须 URL 编码。别猜,直接用 rawurlencode() 处理密码再填进配置。


















