Laravel多租户环境下数据库会话存储位置及存储异常问题
问题原因
Laravel的Session组件默认会使用config/database.php中配置的默认数据库连接(通常是公共连接)来读写会话表。哪怕InitializeTenancyByRequestData中间件切换了当前请求的数据库上下文,Session组件在请求初始化阶段就已经绑定了默认连接,不会自动跟随中间件的连接切换而更新,所以会话数据还是会写到公共schema的表里。
解决方案
1. 全局配置Session使用租户连接(推荐)
直接在config/session.php里指定Session使用租户专用的数据库连接:
// config/session.php return [ // ...其他配置项 'connection' => 'tenant', // 此处填写你的租户连接名称,对应database.php中的配置项 ];
这样所有经过租户初始化中间件的请求,Session都会自动使用租户连接,读写租户schema里的会话表。
2. 动态切换Session连接(按需使用)
如果需要部分路由用租户会话、部分用公共会话,可以自定义中间件动态切换Session连接:
首先创建中间件:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Config; class SetTenantSessionConnection { public function handle($request, Closure $next) { if (tenancy()->initialized) { // 切换Session连接到租户连接 Config::set('session.connection', 'tenant'); // 重置Session实例,确保使用新连接 app()->forgetInstance('session.store'); $request->session()->start(); } return $next($request); } }
然后在路由中把这个中间件放在租户初始化中间件之后:
Route::get('/test', function() { session(['key' => 'value']); return response()->json(session('key')); }) ->middleware([ Stancl\Tenancy\Middleware\InitializeTenancyByRequestData::class, App\Http\Middleware\SetTenantSessionConnection::class ]);
会话存储位置建议
- 如果是租户专属会话(比如租户后台的登录状态、租户内的临时操作数据):存在租户schema更合理,避免跨租户会话冲突,也符合租户数据隔离的原则。
- 如果是系统公共会话(比如前台未登录用户的临时数据、全局登录状态):存在公共schema更合适。
内容的提问来源于stack exchange,提问作者Danny Adams
相关产品推荐
相关产品推荐

