ThinkPHP 8.0多应用会话共享失效源于Session中间件未启用、存储驱动与prefix不统一、Cookie作用域未设为跨子域。需修改app/middleware.php启用SessionInit,配置session.php使用统一Redis存储及空prefix,设置cookie_domain为.example.com,并确保Nginx透传Cookie域及前端AJAX携带credentials。

ThinkPHP 8.0多应用模式下,www.example.com和admin.example.com登录后互相丢失会话,不是代码写错了,而是Session存储路径、Cookie作用域、中间件加载位置三处配置同时错位导致的连锁失效。
确认Session中间件是否真正启用
新建项目后Session默认不生效,因为SessionInit中间件未被正确加载。官方文档写的config/middleware.php是误导性路径——实际应修改app/middleware.php文件。
打开app/middleware.php,将\think\middleware\SessionInit::class加入返回数组第一项;若该文件为空,请直接写成:return [\think\middleware\SessionInit::class];
执行php think clear清除运行时缓存,否则旧配置仍被读取。这一步漏掉,后续所有配置都白做。
立即学习“PHP免费学习笔记(深入)”;
统一Session存储驱动与前缀
子应用间Session无法共享,首要原因是默认file驱动各自写本地文件。必须切换为Redis或Database驱动,并确保所有应用共用同一存储实例和完全一致的prefix。
在config/session.php中强制指定:
'type' => 'redis','prefix' => '','store' => 'session'
【prefix必须为空字符串或所有子应用完全一致】,否则www应用写sess_abc,admin应用却去读admin_sess_abc,自然找不到。
同时在config/cache.php中确认stores.session配置指向真实可用的Redis实例,host、port、database、auth缺一不可。
设置跨子域有效的Cookie作用域
即使Session数据已统一存储,浏览器仍按域名隔离发送Cookie。若不显式声明作用域,www.example.com设的Cookie不会发给admin.example.com。
方法一:在config/session.php中添加
'cookie_domain' => '.example.com'
注意开头的点不能省略,写成example.com或www.example.com均无效。
方法二:若部署在Nginx反向代理后,还需追加响应头透传规则:
proxy_cookie_domain ~^(.+)$ .example.com;
否则Nginx会覆盖PHP设置的domain值,导致前端始终收不到带正确domain的Set-Cookie头。
验证Session ID是否真正复用
第一步:在www应用登录接口中打印session_id(),记录返回值如abc123;
第二步:立即访问admin应用任意接口,在其控制器中再次打印session_id();
第三步:比对两个ID是否完全相同。若不同,说明Session未共享成功;若相同但Session::get()取不到数据,则是prefix或store配置不一致。
前端请求必须携带凭证:AJAX调用需设credentials: 'include',否则浏览器根本不会发送Cookie头,服务端连Session ID都收不到。



















