Laravel 12 中子域名跨域需动态配置 CORS:使用 allowed_origin_patterns(如 'https://*.example.com')或闭包匹配 Host,启用 supports_credentials 并设 SESSION_DOMAIN=.example.com,中间件须注册于 api 组且路由后生效。

在 Laravel 12 中处理子域名(如 api.example.com 或 shop.example.com)的 CORS 配置,不能简单套用普通跨域方案。因为子域名属于**不同源**(https://example.com ≠ https://api.example.com),浏览器会触发严格同源检查;同时,若需共享 Cookie 或认证凭证(如 Sanctum 的 session),还需额外注意 Access-Control-Allow-Origin 与 credentials 的兼容性。
明确子域名是否需要独立 CORS 规则
先判断场景:
- 前端在
app.example.com,后端 API 在api.example.com→ 属于跨子域,必须配置 CORS - 多个租户子域(
tenant1.example.com、tenant2.example.com)各自调用同一后端(如api.example.com)→ 后端需动态允许对应子域,而非固定列表 - 子域名本身是 Laravel 应用入口(如
admin.example.com跑后台),且它又调用自己 API(admin.example.com/api/xxx)→ 实际是同源,无需 CORS
推荐方式:用 fruitcake/laravel-cors + 动态 origins
Laravel 12 兼容 fruitcake/laravel-cors(v3+),它支持闭包形式的 allowed_origins,可实时解析 Host 头并匹配子域名。
步骤如下:
- 安装包:
composer require fruitcake/laravel-cors - 发布配置:
php artisan vendor:publish --tag="cors" - 编辑
config/cors.php,将allowed_origins改为闭包:
‘allowed_origins’ => function ($request) {
$host = $request->getHost();
// 允许所有一级子域(不含 www 和主域)
if (preg_match('/^([a-z0-9\-]+)\.example\.com$/i', $host, $matches)) {
return 'https://' . $host;
}
// 开发环境允许 localhost:*
if (str_starts_with($host, 'localhost:')) {
return 'http://' . $host;
}
return null;
},
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
- 确保
supports_credentials设为true(若需传 Cookie 或 XSRF-Token) - 同时设置
allowed_origin_patterns(Laravel 12+ 原生支持)更简洁:
‘allowed_origin_patterns’ => [
'https://*.example.com',
'http://localhost:*'
],
该配置比正则更轻量,且由框架底层直接匹配 Host,无需手动解析。
配合子域名路由时的中间件注册位置
若你已用 Route::domain('{sub}.example.com') 分发请求,CORS 中间件必须在**路由匹配之后、控制器执行之前**生效。因此:
- 不要仅放在全局
$middleware(可能对非 API 请求误加头) - 推荐注册到
$middlewareGroups['api'],并确保子域名下的 API 路由使用api中间件组 - 例如在
RouteServiceProvider中:
Route::domain('{sub}.example.com')
->middleware('api') // 自动包含 HandleCors
->group(base_path('routes/api.php'));
注意事项:Cookie 与 credentials 安全要求
当启用 supports_credentials => true 时:
-
Access-Control-Allow-Origin不能为*,必须是具体域名(如https://app.example.com) - 前端发起请求时须设
credentials: 'include' - Laravel 的 Session/Cookie 需配置
SESSION_DOMAIN=.example.com(注意开头的点),才能被所有子域共享 - Nginx/Apache 若反向代理了子域名,需透传
Origin和Host头,否则$request->getHost()取到的是代理 IP

















