如何防止超级管理员凭证登录租户环境?Laravel多租户问题
解决Laravel Jetstream多租户认证隔离问题
1. 彻底隔离主站与租户的路由域
之前的域名分组未生效,是因为未将Jetstream的认证路由纳入中央域名范围。修改routes/web.php,把主站所有路由(含Jetstream认证路由)包裹在中央域名分组内,确保仅主域名可访问:
<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\ClientController; use Laravel\Jetstream\Jetstream; // 仅中央域名可访问的主站路由组 foreach (config('tenancy.central_domains') as $domain) { Route::domain($domain)->group(function () { // 手动注册Jetstream主站认证路由(需先在config/jetstream.php关闭自动路由) Jetstream::routes(); // 主站认证后路由 Route::middleware([ 'web', 'auth', config('jetstream.auth_session'), 'verified', ])->group(function () { Route::resource('clients', ClientController::class); Route::get('/dashboard', function () { return view('dashboard'); })->name('dashboard'); }); }); }
同时修改config/jetstream.php关闭自动路由加载:
'routes' => false,
2. 为租户搭建独立认证系统
在routes/tenant.php中添加租户专属的认证路由与受保护路由,确保租户使用独立的用户体系:
<?php declare(strict_types=1); use Illuminate\Support\Facades\Route; use Stancl\Tenancy\Middleware\InitializeTenancyByDomain; use Stancl\Tenancy\Middleware\PreventAccessFromCentralDomains; use App\Http\Controllers\Tenant\Auth\LoginController; use App\Http\Controllers\Tenant\DashboardController; Route::middleware([ 'web', InitializeTenancyByDomain::class, PreventAccessFromCentralDomains::class, ])->group(function () { // 租户登录/登出路由 Route::get('/login', [LoginController::class, 'showLoginForm'])->name('tenant.login'); Route::post('/login', [LoginController::class, 'login']); Route::post('/logout', [LoginController::class, 'logout'])->name('tenant.logout'); // 租户认证后路由(需搭配专属Guard与校验中间件) Route::middleware([ 'auth:tenant', 'tenant.user', 'verified', ])->group(function () { Route::get('/dashboard', [DashboardController::class, 'index'])->name('tenant.dashboard'); // 其他租户业务路由 }); });
3. 配置多Guard区分用户体系
修改config/auth.php,新增tenant Guard,关联租户用户模型与租户数据库连接:
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'tenant' => [ 'driver' => 'session', 'provider' => 'tenant_users', ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, // 主站用户模型(存中央库) ], 'tenant_users' => [ 'driver' => 'eloquent', 'model' => App\Models\Tenant\User::class, // 租户用户模型(存租户库) ], ],
租户用户模型需指定连接:
// App\Models\Tenant\User.php protected $connection = 'tenant';
4. 添加租户用户校验中间件
创建EnsureTenantUser中间件,确保登录用户属于当前租户:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class EnsureTenantUser { public function handle(Request $request, Closure $next) { $user = Auth::guard('tenant')->user(); // 校验用户归属当前租户(根据你的数据结构调整判断逻辑) if (! $user || $user->tenant_id !== tenant('id')) { Auth::guard('tenant')->logout(); return redirect()->route('tenant.login')->withErrors(['email' => '无权访问该租户系统']); } return $next($request); } }
在app/Http/Kernel.php注册中间件:
protected $routeMiddleware = [ // ... 'tenant.user' => \App\Http\Middleware\EnsureTenantUser::class, ];
最终效果
- 主站登录/注册仅中央域名可访问,租户域名访问会触发路由不存在
- 租户域名使用独立登录系统,仅租户数据库内的用户可登录
- 主站超级管理员无法登录租户系统,租户用户也无法访问主站认证页
内容的提问来源于stack exchange,提问作者Ashish Cherry2
相关产品推荐
相关产品推荐

