Laravel:管理员子域名路由配置与跨域访问权限限制咨询
Hey there! Let's walk through how to set up this domain-specific access control in Laravel—this is a common requirement, and I’ve got a solid, straightforward approach for you:
First, split your routes into two groups in routes/web.php: one for your main domain (regular users) and one for the admin subdomain. This makes it easy to apply different access rules later.
// routes/web.php use App\Http\Controllers\HomeController; use App\Http\Controllers\AdminDashboardController; use App\Http\Controllers\AdminStatisticsController; // Main domain routes (for regular users) Route::domain('domain.com')->group(function () { Route::get('/', [HomeController::class, 'index'])->name('home'); // Add all other regular user-facing routes here }); // Admin subdomain routes Route::domain('admin.domain.com')->group(function () { Route::get('/', [AdminDashboardController::class, 'index'])->name('admin.dashboard'); Route::get('/statistics', [AdminStatisticsController::class, 'index'])->name('admin.statistics'); // Add all other admin-only routes here });
We need two middleware: one to lock admins to the subdomain, and another to block admins from the main domain while restricting regular users to it.
Create the Admin Subdomain Middleware
Run this command to generate the middleware:
php artisan make:middleware EnsureIsAdminOnSubdomain
Open the generated file at app/Http/Middleware/EnsureIsAdminOnSubdomain.php and add this logic:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Symfony\Component\HttpFoundation\Response; class EnsureIsAdminOnSubdomain { public function handle(Request $request, Closure $next): Response { // Redirect unauthenticated users to the admin login page if (!Auth::check()) { return redirect()->route('admin.login'); } // Block access if the user isn't on the admin subdomain if ($request->getHost() !== 'admin.domain.com') { abort(403, 'You are not authorized to access this area.'); } // Verify the user has admin privileges // Adjust this check to match your role system (e.g., hasRole('admin')) if (!Auth::user()->is_admin) { abort(403, 'You do not have admin permissions.'); } return $next($request); } }
Create the Regular User Main Domain Middleware
Generate the second middleware:
php artisan make:middleware EnsureIsRegularUserOnMainDomain
Add this logic to app/Http/Middleware/EnsureIsRegularUserOnMainDomain.php:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Symfony\Component\HttpFoundation\Response; class EnsureIsRegularUserOnMainDomain { public function handle(Request $request, Closure $next): Response { // Redirect unauthenticated users to the main login page if (!Auth::check()) { return redirect()->route('login'); } // Block access if the user isn't on the main domain if ($request->getHost() !== 'domain.com') { abort(403, 'You are not authorized to access this area.'); } // Block admins from accessing the main domain if (Auth::user()->is_admin) { abort(403, 'Admin users cannot access the main domain area.'); } return $next($request); } }
Open app/Http/Kernel.php and add your new middleware to the $routeMiddleware array:
protected $routeMiddleware = [ // ... existing middleware 'admin.subdomain' => \App\Http\Middleware\EnsureIsAdminOnSubdomain::class, 'regular.user.main' => \App\Http\Middleware\EnsureIsRegularUserOnMainDomain::class, ];
Update your route groups to enforce the access rules using the middleware you just created:
// Main domain routes (regular users only) Route::domain('domain.com')->middleware('regular.user.main')->group(function () { Route::get('/', [HomeController::class, 'index'])->name('home'); // Other regular user routes... }); // Admin subdomain routes (admins only) Route::domain('admin.domain.com')->middleware('admin.subdomain')->group(function () { Route::get('/', [AdminDashboardController::class, 'index'])->name('admin.dashboard'); Route::get('/statistics', [AdminStatisticsController::class, 'index'])->name('admin.statistics'); // Other admin routes... });
If you want separate login pages for admins and regular users, add those routes to their respective domain groups:
// Main domain login Route::domain('domain.com')->get('/login', [AuthController::class, 'showLoginForm'])->name('login'); Route::domain('domain.com')->post('/login', [AuthController::class, 'login']); // Admin subdomain login Route::domain('admin.domain.com')->get('/login', [AdminAuthController::class, 'showLoginForm'])->name('admin.login'); Route::domain('admin.domain.com')->post('/login', [AdminAuthController::class, 'login']);
In your login controllers, redirect users to the correct domain after successful login:
- For regular users:
return redirect()->route('home'); - For admins:
return redirect()->route('admin.dashboard');
To test this locally, edit your computer's hosts file to map the domains to your local server:
127.0.0.1 domain.com 127.0.0.1 admin.domain.com
Then access your app via http://domain.com and http://admin.domain.com in your browser.
- Role System: If you're using a more complex role system (e.g., Spatie Laravel Permissions), replace the
is_admincheck with something likeAuth::user()->hasRole('admin'). - Custom 403 Page: Create a
resources/views/errors/403.blade.phpfile to show a friendly error message instead of the default Laravel 403 page. - Session Sharing: By default, Laravel shares sessions across subdomains if your
config/session.phphas'domain' => '.domain.com'. If you don't want admins to have sessions on the main domain, set the session domain to'domain.com'for regular users and'admin.domain.com'for admins (you can adjust this dynamically in middleware if needed).
内容的提问来源于stack exchange,提问作者Nenad Kaevik

