根本原因是浏览器cookie作用域机制与php session存储逻辑共同导致;解决需统一redis/database存储、设cookie_domain为.example.com、前端请求带credentials且后端cors允许凭据。

ThinkPHP 配置二级域名后 Session 和 Cookie 无法自动共享,根本原因不是框架限制,而是浏览器的 Cookie 作用域机制和 PHP 底层 Session 存储逻辑共同导致的。解决的关键是三件事:统一存储、正确设域、前后端协同。
必须换掉 file 驱动,用 Redis 或 Database
默认的 file 驱动在多子域下完全失效——每个应用往自己服务器本地写 session 文件,彼此读不到。Memcached 在 TP6 中存在过期策略不稳定问题,官方不推荐。
- Redis 是首选:所有子域应用(如 www.example.com、admin.example.com、api.example.com)连接同一 Redis 实例,session_id 作为 key 写入,天然可跨域读取
- Database 也可行:共用一张 think_session 表,注意表结构一致、数据库连接配置相同
- TP6 配置入口统一在 config/session.php,关键项必须设为:
'type' => 'redis'(或 'database'),
'prefix' => ''(前缀必须清空或所有应用完全一致,否则 key 对不上)
Cookie 域名必须设为 .example.com(带点开头)
浏览器只允许将 Cookie 发送给匹配 .example.com 的所有子域(包括 www、admin、api)。写成 example.com 或 www.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 设置
跨域请求必须开启 credentials + 显式 CORS
即使 Cookie 域设对了,前端发 AJAX 请求时默认不带 Cookie。浏览器强制要求显式声明。
- 前端请求(如 fetch 或 axios)必须加:
credentials: 'include'(fetch)或 withCredentials: true(axios) - 后端 config/cors.php 必须明确指定来源,不能用 *:
'allow_origin' => ['https://www.example.com', 'https://admin.example.com']
并开启:'allow_credentials' => true - 响应头中必须包含:
Access-Control-Allow-Credentials: true
本地开发调试要避开 localhost
浏览器禁止给 localhost 设置 domain 属性,所以本地测不出效果。
- 建议切到真实二级域名测试,例如:dev.example.com、test.example.com
- 配合 hosts 文件绑定 127.0.0.1 dev.example.com
- 测试前务必清空浏览器 Cookie 和 ThinkPHP 运行缓存(runtime/session 和 runtime/cache)
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











