PHP 8.6 收紧 session 三个默认值:先受影响的是 SAML SSO 和跨域表单
信源:PHP 8.6 feature roundup(2026 年 10 月,PHP 8.6.0 RC3,GA 计划 2026-11-19 发布)。
三个默认值变了
session.use_strict_mode、session.cookie_httponly、session.cookie_samesite 的默认值现在分别是 1、1、Lax。此前它们处于关闭或未设置状态。
对应的 SessionHandler::validateId() 这次真正实现了——这也是 Strict Mode 能生效的前提,之前该模式下缺少实际校验实现。
后果是行为变化:
- 外部提供或共享的 session ID 会被拒绝;
- JavaScript 通过
document.cookie读不到 session cookie; - 跨站 POST 流程(SP 发起的 SAML SSO、较老式的跨域表单)需要显式声明
SameSite=None; Secure。
排查顺序
- Strict Mode 优先:登录态建立失败、session 反复重建、上游系统透传的 session ID 不再被接受,先看这一类。外部注入或复用的 ID 现在直接被拒。
- 前端读取 cookie:搜索依赖
document.cookie拿 session cookie 的代码,cookie_httponly=1之后这条路走不通。 - 跨站 POST:SP 发起的 SAML SSO、老式跨域表单提交,是
SameSite=Lax下最先暴露的场景,需要SameSite=None; Secure。 - 收窄作用范围:先确认跨站需求是否真的覆盖整个应用。通常只有单个登录端点涉及跨站流程,不必把配置扩散到全站。
显式配置
php.ini 侧按需覆盖:
; 默认值本身(8.6 起生效,通常无需显式写出)
session.use_strict_mode = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
跨站 POST 场景:
session.cookie_samesite = None
session.cookie_secure = On
Symfony 不走 ini_set(),改在 framework 配置里:
# config/packages/framework.yaml
# only needed if your setup depends on cross-site POST
framework:
session:
cookie_samesite: none
cookie_secure: true
为什么不建议全局放宽
把 cookie_samesite 全站设成 none、关掉 httponly、或者回退 use_strict_mode,等于一次性放弃这三项默认收紧带来的防护收益:Strict Mode 重新允许外部指定 session ID,httponly 失效后 cookie 暴露给脚本,SameSite=None 则让跨站请求重新携带 session cookie。
原文给出的判断也很直接:先确认是否必须作用于整个应用,跨站流程往往只涉及单个登录端点——把这个端点单独配置,其余保持新默认值。
8.6 其它变更
- partial function application v2(
?与...) clamp()Time\DurationIo\Poll- 带默认值的 readonly 属性
grapheme_strrev()json_decode()的错误信息现在会给出 payload 中的位置#[Override]同样适用于类常量- PFA 限制:构造函数不能被部分应用;引用的特殊规则;
func_get_args()行为不同 - Deprecations for PHP 8.6 RFC:31 项接受,4 项拒绝;这些弃用在 8.6 中表现为
E_DEPRECATED,最早在 PHP 9.0 移除