laravel 7 cors异常实为浏览器拦截或配置失效所致,需从中间件注册、credentials与origin匹配、options请求处理三方面排查;须用fruitcake包、正确注册handlecors中间件、禁用allowed_origins为*、nginx放行options。

确认中间件是否真正生效
这是 90% “CORS 不生效”问题的根源,看似配置了,实则中间件根本没运行:
- 检查
app/Http/Kernel.php中是否将\Fruitcake\Cors\HandleCors::class加入到正确的中间件组(不要加在全局$middleware,推荐加在$middlewareGroups['api']) - 确保你的路由确实走的是
api组(如routes/api.php中定义,且 RouteServiceProvider 中已绑定->middleware('api')) - 运行
php artisan config:clear清除配置缓存,否则config/cors.php修改无效
避免 supports_credentials 与 allowed_origins 冲突
这是最典型的“静默失败”场景:前端带 cookie 发请求,后端返回 200 但浏览器仍拦截,控制台报错却无后端日志——因为浏览器在预检阶段就拒绝了。
-
'supports_credentials' => true时,'allowed_origins'绝对不可为['*']
- 必须写明确域名:
['http://localhost:3000', 'https://admin.example.com'] - 前端 fetch 需同步设置
credentials: 'include',否则后端即使允许也无意义
捕获并记录 OPTIONS 预检失败
如果浏览器发了 OPTIONS 请求但后端没响应(Nginx 拦截、路由未匹配、中间件提前终止),你不会在 Laravel 日志里看到任何记录——它根本没进 Laravel。
- 在 Nginx 配置中显式放行 OPTIONS:
if ($request_method = 'OPTIONS') { add_header ...; return 200; } - 在
routes/api.php添加兜底 OPTIONS 路由(尤其调试期):Route::options('{any}', function () { return response('', 200); })->where('any', '.*'); - 用 Chrome DevTools → Network → 筛选
OPTIONS,看请求是否发出、响应状态码及响应头内容
自定义响应头异常兜底(可选)
若需统一处理 CORS 相关响应逻辑(如动态判断 origin、记录非法跨域尝试),可创建轻量中间件替代 fruitcake 包:
- 执行
php artisan make:middleware CorsResponse - 在
handle()中添加 origin 白名单校验,并对非法 origin 返回 403 或空响应 - 对 OPTIONS 请求直接
return response('', 200)并附加必要头,避免进入完整请求生命周期 - 该中间件应放在
EncryptCookies和StartSession之后、路由中间件之前











