You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止超级管理员凭证登录租户环境?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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 10:34:51