Laravel 13 中通过自定义中间件校验 Origin 请求头并匹配白名单域名(如 https://admin.yourapp.com、http://localhost:3000)实现 API 域名限制,需配合 CORS 配置共同生效,且不能替代服务端鉴权。

在 Laravel 13 中,要限制 API 仅允许自家域名(如 https://admin.yourapp.com 或 http://localhost:3000)调用,核心是校验请求头中的 Origin(浏览器跨域请求)或 Referer(部分非浏览器客户端),并结合中间件做白名单拦截。注意:该限制本质是「前端层面友好提示」,不能替代服务端鉴权(如 API Token、JWT),因为请求头可被伪造。
确认请求来源是否为可信域名
浏览器发起的跨域 AJAX/Fetch 请求会自动带上 Origin 头,这是最可靠、标准的判断依据。中间件中应优先检查它:
- 获取请求 Origin:
$origin = $request->headers->get('Origin'); - 定义白名单数组(建议从配置文件读取,便于环境区分):
config('app.allowed_origins', ['https://admin.yourapp.com', 'https://app.yourapp.com', 'http://localhost:3000']) - 严格比对:使用
in_array($origin, $allowed),不推荐模糊匹配或正则(易绕过) - 若 Origin 为空(如 curl 直接调用、Postman、服务端内部请求),需根据业务决定是否放行——通常应拒绝,除非明确需要后端调用
创建并注册域名校验中间件
运行命令生成中间件:
php artisan make:middleware AllowOwnDomains
编辑 app/Http/Middleware/AllowOwnDomains.php,在 handle 方法中写入逻辑:
public function handle($request, Closure $next)<br>{<br> $origin = $request->headers->get('Origin');<br> $allowed = config('app.allowed_origins', []);<br><br> if (!$origin || !in_array($origin, $allowed)) {<br> abort(403, 'Access denied: Origin not allowed');<br> }<br><br> return $next($request);<br>}
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
然后在 app/Http/Kernel.php 的 $routeMiddleware 数组中注册:
'domain-check' => \App\Http\Middleware\AllowOwnDomains::class,
应用到 API 路由并处理预检请求(OPTIONS)
在 routes/api.php 中为需要保护的路由组添加中间件:
Route::middleware(['api', 'domain-check'])->group(function () {<br> Route::get('/data', [DataController::class, 'index']);<br>});
⚠️ 注意:浏览器跨域请求前会先发一个 OPTIONS 预检请求。Laravel 默认的 api 中间件组已包含 \Fruitcake\Cors\HandleCors::class(Laravel 9+ 内置),它会自动响应 OPTIONS 并设置 CORS 头。但如果你手动写了中间件且未兼容 OPTIONS,需确保它不中断预检流程——上面的 AllowOwnDomains 已通过 abort(403) 统一处理,对 OPTIONS 同样生效,符合预期。
补充:配合 CORS 配置更安全
仅靠中间件拦截不够完整。建议同步配置 Laravel 的 CORS 设置,让合法域名能真正完成跨域通信:
- 确保
config/cors.php中'paths'包含你的 API 路径(如['api/*']) -
'allowed_origins'应与中间件白名单一致,例如:['https://admin.yourapp.com', 'https://app.yourapp.com'] - 若需携带 Cookie 或认证头,开启
'supports_credentials' => true,并确保前端请求也设置credentials: 'include' - 中间件负责「拒绝非法来源」,CORS 配置负责「允许合法来源通信」,二者协同才完整

















