tp6跨应用session共享失效的核心原因是各应用默认隔离、初始化错位、驱动配置未对齐及cookie域不统一;必须在每个应用middleware.php中显式注册sessioninit中间件、统一cookie_domain为'.example.com'、redis配置含相同prefix、关键操作后调用session::save()并确保前端credentials: 'include'。

TP6 跨应用 Session 共享失效,核心不是“不能共享”,而是各应用默认隔离、Session 初始化时机错位、驱动配置未对齐、Cookie 域不统一——只要任一环节缺失,就会出现“A 应用登录了,B 应用取不到 session”“语言切换只在前台生效,后台管理始终英文”等问题。
Session 初始化必须提前且全局一致
多应用(如 admin、api、home)各自维护 middleware.php,若只在主应用注册 \think\middleware\SessionInit::class,其他子应用的请求根本不会触发 Session 启动,session('user_id') 直接返回 null。
- 每个应用目录下的
app/middleware.php都要显式加入\think\middleware\SessionInit::class - 该中间件必须排在所有依赖 Session 的中间件之前(如
Auth、Lang、自定义权限中间件) - 不要在控制器里用
session_start()或Session::init()补救——TP6 已移除这些方式,无效且易引发重复启动警告
Cookie 域与 Session 域必须严格对齐
即使 Session 数据存 Redis,跨应用共享仍依赖浏览器把同一个 PHPSESSID Cookie 发给所有子域。若 Cookie 作用域仅限 admin.example.com,则 api.example.com 根本收不到该 ID,自然无法读取对应 Session。
- 在所有应用的
config/app.php中统一设置:'cookie_domain' => '.example.com'(注意开头的点) - 同时在各应用的
app/middleware.php开头(return []之前)加:ini_set('session.cookie_domain', '.example.com'); - 本地开发禁用
localhost;改用test.example.com+ hosts 绑定,否则点域名规则不生效 - HTTPS 环境下,还需开启:
'cookie_secure' => true和'session.cookie_secure' => true
Redis 驱动配置需完全一致且显式声明
不同应用若使用不同 Redis 实例、不同 prefix、甚至一个用 file 一个用 redis,必然导致 Session 数据物理隔离。TP6 不 fallback,配置缺项即静默禁用 Session。
- 所有应用的
config/app.php中'session'数组必须含:'type' => 'redis'和完整'redis_config'(含'hostname'、'hostport'、'password') -
'prefix'必须设为相同非空字符串(如'shared:'),避免 key 冲突或被其他项目覆盖 - 确认已执行:
composer require topthink/think-session—— 缺失该扩展时,TP6 自动降级为 file 驱动,且不报错 - 若原系统有 TP5.1 迁移数据,需统一序列化器:
'serializer' => \think\session\serializer\PhpSerializer::class
Session 写入必须手动触发并确保流程完整
TP6 默认延迟写入:赋值进 Session 只缓存在内存,响应结束前不调 Session::save(),数据就不会落库。跨应用场景下,若 A 应用设了 session 但没保存,B 应用自然读不到。
- 在登录、语言切换、验证码生成等关键操作后,立即加:
\think\facade\Session::save(); - 推荐统一放在基类
BaseController::initialize()末尾,或自定义中间件的after()方法中 - 严禁在逻辑中途使用
exit、die、throw new HttpException(404)等提前终止——save() 将被跳过 - 前端发起跨域请求时,务必带
credentials: 'include',否则浏览器不发送 Cookie











