ThinkPHP 6.x Session跨域共享核心是统一存储驱动、正确设置作用域并区分子域与主域方案:必须用redis或database替代file驱动;子域名设cookie_domain为.example.com并确保PHP/Nginx生效;跨主域需前端透传session_id并后端校验。

ThinkPHP 6.x 的 Session 跨域共享,核心不在“怎么传 Cookie”,而在于“数据存哪、谁来读、作用域是否对”。文件驱动天然不支持多域名共享,必须换存储;子域名和主域名的处理方式完全不同,不能混用一套方案。
必须统一 Session 存储驱动
默认的 file 驱动在多域名或负载均衡下完全失效——每个应用写本地文件,彼此看不到对方的 session 数据。Memcached 在 TP6 中存在过期策略不稳定问题,官方也不推荐。
- Redis 是首选:所有应用连接同一 Redis 实例,session_id 作为 key 写入,天然可跨应用读取
-
Database 也可行:共用一张 session 表(如
think_session),注意表结构一致、连接配置相同 - TP6 配置入口统一在
config/session.php,关键项:'type' => 'redis'或'type' => 'database''prefix' => ''(必须清空或所有应用保持完全一致)
子域名共享:靠 Cookie 域名设置
适用于 admin.example.com、api.example.com、www.example.com 这类同主域场景。浏览器只允许把 Cookie 发送给匹配 .example.com 的所有子域。
- 在
config/session.php中设置:'cookie_domain' => '.example.com' - 同时确保 PHP 层生效(尤其反向代理环境):
ini_set('session.cookie_domain', '.example.com');必须在session_start()之前执行 - Nginx 反向代理需加:
proxy_cookie_domain ~^(.+)$ .example.com;,否则会覆盖原始 domain
跨主域共享:放弃 Cookie,手动透传 session_id
像 a.com 和 b.net 这种不同主域,浏览器禁止共享 Cookie,没有绕过办法。只能由前端显式携带 ID,后端主动加载。
立即学习“PHP免费学习笔记(深入)”;
- 登录成功后,前端获取当前 session_id:
fetch('/login', { method: 'POST' }).then(r => r.json()).then(data => { const sid = data.sid; /* 存 localStorage 或传给其他域 */ }) - 目标域接收时,在
session_start()前强制指定:if (!empty($_GET['sid'])) { session_id($_GET['sid']); } - 务必校验有效性(如 Redis 中
exists think_session:xxx),防止伪造 ID - TP6 的
think\facade\Session不支持运行时切换 ID,必须用原生session_id()
配套要点不能漏
光改驱动和 domain 不够,以下细节出错会导致前功尽弃:
- session.name 保持默认(PHPSESSID),不要随意改,避免前端/代理识别错
- 所有应用使用相同 session_lifetime 和 gc_maxlifetime,否则一个删了另一个还读着过期数据
-
开启 credentials:前端 fetch 要加
{ credentials: 'include' },Axios 配withCredentials: true -
跨域响应头要带 Allow-Credentials:TP6 可直接启用
\think\middleware\AllowCrossDomain::class,它自动包含Access-Control-Allow-Credentials: true



















