laravel 5 中需手动配置 cors:推荐在 routes/api.php 的路由组后使用 ->withheaders() 设置响应头,或创建自定义 cors 中间件并注册到 api 中间件组,同时必须显式添加 options 预检路由。

在 Laravel 5(如 5.7/5.8)中配置 CORS,**不能依赖内置的 `HandleCors` 中间件**(该中间件从 Laravel 8+ 才由 `fruitcake/laravel-cors` 提供并深度集成),因此需手动为路由组添加跨域响应头。核心思路是:**对特定路由组(如 API 路由)统一应用自定义中间件或直接注入响应头**,避免逐个路由设置。
给 API 路由组添加 CORS 响应头(推荐)
由于 Laravel 5 默认不带 CORS 中间件,最稳妥的方式是在 `routes/api.php` 中,用 `Route::group()` 包裹所有 API 路由,并通过 `->middleware()` 或 `->withHeaders()` 统一控制:
- 打开 routes/api.php,将所有 API 路由放入一个分组中(Laravel 5.8 默认已有此结构)
- 在分组后链式调用 ->withHeaders(),例如:
Route::group(['prefix' => 'api'], function () {
Route::get('/users', 'Api\UserController@index');
Route::post('/login', 'Api\AuthController@login');
});
->withHeaders([
'Access-Control-Allow-Origin' => 'http://localhost:3000',
'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers' => 'Content-Type, X-Requested-With, Authorization',
'Access-Control-Allow-Credentials' => 'true'
]); - 注意:
->withHeaders()必须放在整个Route::group()表达式之后(即分号前),且仅适用于 Laravel 5.5+;若无效,请改用中间件方式
为路由组注册自定义 CORS 中间件
若需更灵活控制(如动态判断来源、处理 OPTIONS 预检),建议手写中间件:
- 执行
php artisan make:middleware Cors创建中间件 - 编辑 app/Http/Middleware/Cors.php,在
handle()方法中添加响应头:
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('Access-Control-Allow-Origin', 'http://localhost:3000');
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
$response->headers->set('Access-Control-Allow-Headers', 'Content-Type, X-Requested-With, Authorization');
$response->headers->set('Access-Control-Allow-Credentials', 'true');
return $response;
} - 在 app/Http/Kernel.php 的
$middlewareGroups['api']数组中加入该中间件:
'App\Http\Middleware\Cors' - 确保你的 API 路由确实使用了
api中间件组(默认 routes/api.php 已自动绑定)
特别注意 OPTIONS 预检请求
Laravel 5 不自动响应 OPTIONS 请求,前端发预检时容易返回 405 错误:
- 在 routes/api.php 顶部或对应位置,显式添加一条空 OPTIONS 路由:
Route::options('{any}', function () {
return response('', 200)
->header('Access-Control-Allow-Origin', 'http://localhost:3000')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'Content-Type, X-Requested-With, Authorization');
where('any', '.*'); - 该路由需放在所有其他路由之前,且不能被认证中间件包裹(预检请求无 token)
- 若只针对某几个接口开放跨域,可单独写
Route::options('/api/login', ...)
开发与生产环境差异处理
不要在生产环境用 '*' 作为 Access-Control-Allow-Origin 值(尤其开启 credentials 时):
- 开发时可设为
'http://localhost:3000'或'http://127.0.0.1:3000'(注意协议、域名、端口必须完全匹配) - 生产环境建议读取配置项:
'Access-Control-Allow-Origin' => config('app.cors_origin', 'https://your-app.com')
并在.env中设置CORS_ORIGIN=https://your-app.com - 若需支持多个域名,中间件中可做白名单校验:
$origin = $request->header('Origin');
if (in_array($origin, ['https://a.com', 'https://b.com'])) {
$response->headers->set('Access-Control-Allow-Origin', $origin);
}











