laravel 8 cors配置失败主因是中间件未正确加载、allowed_origins与supports_credentials冲突、nginx拦截options请求;需检查handlecors是否注册到api组、cors.php中paths和allowed_origins是否匹配、nginx是否透传并响应204。

Laravel 8 配置 CORS 失败,通常不是某一处写错,而是多个环节协同出问题。重点不在“怎么配”,而在“哪一环断了”。下面按真实调试路径分步说明。
检查中间件是否真正加载
fruitcake/laravel-cors 在 Laravel 8 中需手动安装和注册,它不会自动进入中间件栈。
- 确认已执行:
composer require fruitcake/laravel-cors且运行过php artisan vendor:publish --provider="Fruitcake\Cors\CorsServiceProvider" - 打开
app/Http/Kernel.php,检查$middlewareGroups['api']数组是否包含\Fruitcake\Cors\HandleCors::class(不是全局$middleware) - 运行
php artisan route:list,查看目标路由的 middleware 列是否显示cors或属于api组 - 清缓存:
php artisan config:clear和php artisan cache:clear,配置文件修改后不清理就无效
核对 cors.php 关键配置组合
浏览器对带凭证(如 Cookie、Authorization)的跨域请求极其敏感,allowed_origins 和 supports_credentials 必须匹配,否则直接拦截预检请求。
- 若前端用了
credentials: 'include'(Vue Axios 默认开启,React fetch 需显式加),则'supports_credentials' => true,且'allowed_origins'不能是['*'],必须写具体域名,例如['http://localhost:3000', 'https://myapp.com'] -
'paths'必须覆盖你的路由,比如 API 接口在api/posts,就要确保'paths' => ['api/*'];漏配路径等于没开 CORS -
'allowed_headers'要包含前端实际发的头,常见遗漏:Authorization、X-Requested-With、Content-Type;生产环境别用['*'],Nginx 或 CDN 可能过滤
确认 OPTIONS 预检请求是否抵达 Laravel
如果浏览器控制台报错 “Failed to fetch” 或 “CORS header ‘Access-Control-Allow-Origin’ missing”,但 Network 面板里根本看不到 Laravel 返回的响应头,大概率预检请求压根没到 PHP 层。
- 用 curl 模拟预检:
curl -I -X OPTIONS http://your.app/api/posts,看返回状态码和响应头。若返回 405、403 或无 CORS 头,说明被 Nginx/Apache 拦截 - Nginx 配置中,
location ~ ^/api/块内必须显式处理 OPTIONS:if ($request_method = 'OPTIONS') {<br> add_header Access-Control-Allow-Origin "http://localhost:3000";<br> add_header Access-Control-Allow-Methods "GET,POST,OPTIONS,PUT,DELETE";<br> add_header Access-Control-Allow-Headers "Authorization,Content-Type,X-Requested-With";<br> add_header Access-Control-Allow-Credentials "true";<br> return 204;<br> } - 注意:
add_header不继承,必须写在匹配的location块里,不能只放在server级别
验证响应头是否完整返回
一个有效跨域响应至少要同时提供三个关键头,缺一不可:
-
Access-Control-Allow-Origin(值必须与前端 origin 完全一致,含协议+域名+端口) -
Access-Control-Allow-Methods(列出允许的方法,如 GET,POST) - 若启用凭证,还必须有
Access-Control-Allow-Credentials: true - 前端 fetch 需配
credentials: 'include',Axios 需设withCredentials: true,两者必须同步











