先验证HandleCors是否执行:在handle()开头加OPTIONS日志,无日志说明中间件未挂载,有日志但500则查config/cors.php语法或类不存在;再紧盯paths、allowed_origins、supports_credentials、allowed_headers四项配置,顺序错、值冲突或不匹配均导致跨域失败。

跨域报错不是配置没加,而是中间件根本没跑起来,或者 config/cors.php 里的设置和浏览器实际要求对不上。
怎么确认 HandleCors 中间件真在执行?
光看配置文件没用,得验证它是否被触发。最直接的办法是在预检请求(OPTIONS)到达时打日志:
- 打开
app/Http/Middleware/HandleCors.php,在handle()方法开头加:if ($request->method() === 'OPTIONS') {<br> \Log::info('CORS preflight hit', ['origin' => $request->headers->get('Origin')]);<br>} - 用前端发一个带自定义 header(比如
X-Requested-With)的请求,触发预检 - 查
storage/logs/laravel.log:- 没日志 → 请求压根没进这个中间件,检查路由前缀(如
api/)是否属于api中间件组,且该组已启用HandleCors - 有日志但返回
500→ 看日志里有没有ReflectionException或Class not found,常见于config/cors.php里写了不存在的类、闭包语法错误,或用了未安装的扩展
- 没日志 → 请求压根没进这个中间件,检查路由前缀(如
config/cors.php 哪几个键必须盯死?
这四个配置项出错,90% 的跨域失败都源于此:
-
paths:必须覆盖你的 API 路径,例如['api/*', 'sanctum/csrf-cookie']。空数组或没匹配上,中间件直接跳过 -
allowed_origins:开发可写['http://localhost:3000'];生产禁用['*'],尤其开了凭据时——浏览器会直接拒绝 -
supports_credentials:设为true时,allowed_origins必须是具体域名数组,不能含*;同时前端fetch要加credentials: 'include' -
allowed_headers:如果前端发了X-Api-Key或Content-Type: application/json,这里就得显式写['X-Api-Key', 'Content-Type'],不能留空,也不能只靠['*'](部分浏览器不认)
HandleCors 在 Kernel.php 里放哪儿才对?
顺序错了,中间件就等于没装。别塞进全局 $middleware 末尾,也别丢进 web 组里不管 API:
- Laravel 9+ 内置
Illuminate\Http\Middleware\HandleCors,不用装包;Laravel 8 及以下需composer require fruitcake/laravel-cors - 在
app/Http/Kernel.php中,把它放在TrustProxies之后、StartSession和EncryptCookies之前 - 只在
$middlewareGroups['api']里启用,别加到web或全局$middleware数组——否则静态资源、健康检查接口也会被加头,徒增干扰 - 确认
api路由组确实绑定了它:php artisan route:list看目标路由的Middlewares列是否含handle-cors
OPTIONS 预检失败,405 错误怎么破?
这不是 CORS 配置问题,是 Laravel 根本没响应预检请求。浏览器发 OPTIONS,后端却返回 405 Method Not Allowed,说明路由没兜住:
- 确保
routes/api.php里有对应路径的Route::options()定义,哪怕只是空的:Route::options('/api/{any}', fn () => response(''))->where('any', '.*'); - 这个
options路由不能被auth:sanctum或其他认证中间件包裹——预检请求不含 token,认证中间件会直接拒掉 - 用
curl -I -X OPTIONS http://your.app/api/endpoint检查响应头,重点看:Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Credentials是否齐全——少一个,前端照样卡住
最容易被忽略的是:浏览器对 Access-Control-Allow-Origin 和 supports_credentials 的互斥限制是硬性的,Laravel 挡不住也改不了。哪怕其他所有配置都对,只要这两项冲突,请求就必然失败。



















