PHP 8.5.5 会话超时需三者协同:客户端 Cookie 过期(由 session_set_cookie_params() 控制)、服务端存储 TTL(如 Redis 的 EXPIRE)、GC 阈值(session.gc_maxlifetime),缺一不可;该配置仅决定 GC 判定过期的阈值,不直接控制 session_id 有效期或用户无操作登出时长。

PHP 8.5.5 的会话超时不是单靠改一个配置就能生效的,必须同时控制客户端 Cookie 过期、服务端存储存活、垃圾回收触发三者,缺一不可。
session.gc_maxlifetime 控制什么、不控制什么
它只决定 PHP 垃圾回收器(GC)认为 session 数据“可能过期”的时间阈值(单位秒),不是 session_id 的有效期,也不等于用户无操作后登出的准确时长。GC 是否真删文件,取决于 session.gc_probability 和 session.gc_divisor 的概率组合——哪怕设成 86400,也可能几分钟就删,也可能几天还在。
- CLI 模式下 GC 完全不触发,
session.gc_maxlifetime形同虚设 - 用 Redis 存 session 时,该配置被忽略,得靠 Redis 自身的
EXPIRE策略 - 文件存储时,若
session.save_path不可写或磁盘满,GC 失败,旧 session 堆积不清理
session_set_cookie_params() 必须在 session_start() 之前调用
浏览器端 Cookie 的过期时间由 session_set_cookie_params() 的 $lifetime 参数决定,不是 session.gc_maxlifetime。这个函数如果写在 session_start() 后面,PHP 不报错但完全无效,Cookie 仍按默认“关闭浏览器即失效”处理。
-
$lifetime = 0:Cookie 随浏览器关闭销毁 -
$lifetime = 3600:Cookie 1 小时后自动过期(即使浏览器没关) - 必须在任何输出(包括空格、BOM、HTML)之前调用
- 只对新生成的 session 生效,不影响已存在的 Cookie
PHP-FPM 环境下改配置最容易踩的坑
phpEnv 或标准 PHP-FPM 部署中,php.ini 里的 session.gc_maxlifetime 常被覆盖。PHP-FPM 的 pool 配置(如 www.conf)中 php_admin_value[session.gc_maxlifetime] 优先级更高,且 ini_set() 在 FPM 下根本不能修改该值。
立即学习“PHP免费学习笔记(深入)”;
- 查真实生效路径:
php-fpm -i | grep 'Loaded Configuration File' - 必须在 pool 配置里加两行:
php_admin_value[session.gc_maxlifetime] = 7200和php_admin_value[session.cookie_lifetime] = 7200 - 改完执行
php-fpm -t校验语法,再systemctl restart phpenv-8.5-fpm(reload 不生效) - Redis 存储时,还要确认
session.save_path中的timeout和database参数正确,且redis.so已在 FPM 的 php.ini 中启用
session.use_strict_mode=1 是安全底线
PHP 8.5.5 默认仍是 0,这意味着攻击者可伪造任意 PHPSESSID,PHP 会自动生成新 session 并返回,造成会话固定漏洞。这不是超时问题,但一旦被利用,用户看似“没超时”,实则 session 已被劫持。
- 必须在
php.ini或 FPM pool 中显式设为1 - 配合
session_regenerate_id(true)在登录成功后强制刷新 ID - 若用 Redis,还需验证 key 的 TTL 是否真按预期设置:
redis-cli TTL sess_abc123
真正让会话“按时超时”的关键,不在某个单一配置,而在三者对齐:Cookie 过期时间、存储后端 TTL、GC 阈值。最容易被忽略的是——你改了配置,却没确认它到底在哪种 SAPI 下生效、也没验证 Redis key 是否真设置了对应过期时间。



















