laravel 5.4需手动处理options预检因无内置corsmiddleware,仅加access-control-allow-origin:*不生效;必须在中间件中显式响应204并校验origin、methods、headers,且凭证请求须指定具体域名而非通配符。

CORS不是后端“加个头就能好”的配置问题,而是浏览器对响应头的硬性校验——Laravel 5.4 默认不带 CORS 支持,必须手动补全中间件逻辑,且不能只设 Access-Control-Allow-Origin: * 就完事。
为什么 Laravel 5.4 的中间件必须手动处理 OPTIONS 预检
Laravel 5.4 没有内置 CorsMiddleware,也不自动拦截或响应 OPTIONS 请求。如果你只在中间件里加了响应头但没处理 OPTIONS 方法,前端发 PUT/DELETE 或带 Authorization 头的请求时,浏览器会卡在预检阶段,控制台报错:Failed to load http://api.test/users: Response to preflight request doesn't pass access control check。
实操建议:
- 在中间件的
handle()方法开头判断$request->method() === 'OPTIONS',直接返回空响应(return response('', 204);) - 不要用
exit或die,否则 Laravel 生命周期中断,日志、事件等可能失效 - 确保
Access-Control-Allow-Methods值和你实际用的请求方法一致,比如用了PUT就必须显式写进列表,不能只写GET, POST
如何安全地设置 Access-Control-Allow-Origin
开发时用 * 看似省事,但一旦你启用了凭证(withCredentials: true),浏览器会直接拒绝响应,报错:The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'。
实操建议:
- 如果前端需要传 Cookie 或 Authorization 头,必须把
Access-Control-Allow-Origin设为具体域名,例如https://localhost:3000(注意:不能带尾部斜杠) - Mac 上本地开发常见组合是
http://localhost:3000(Vue/React) →http://api.test(Laravel Valet),此时Origin是前者,Access-Control-Allow-Origin必须精确匹配前者 - 可以用
$request->header('Origin')动态回写,但务必白名单校验,避免开放给任意来源
遗漏 Access-Control-Allow-Headers 导致上传/鉴权失败
前端用 axios 传 Authorization: Bearer xxx,或用 FormData 上传文件时默认带 Content-Type: multipart/form-data; boundary=xxx,这类请求都会触发预检;若服务端没在 Access-Control-Allow-Headers 里声明对应字段,预检就失败。
实操建议:
- 至少包含:
Content-Type, Authorization, X-Requested-With, Accept - 如果用了自定义头(如
X-Api-Key),必须显式加入该列表 - 不要写
Access-Control-Allow-Headers: *—— 浏览器不认这个通配符,只接受明确列举 - Mac 上用 Valet 或 Homestead 时,Nginx 层可能缓存响应头,改完 PHP 中间件后记得清 Laravel 缓存:
php artisan config:clear,并确认 Nginx 没覆盖响应头
真正容易被忽略的是:CORS 规则生效的前提是响应头必须出现在**最终返回给浏览器的响应中**。Laravel 5.4 的异常处理器(App\Exceptions\Handler)会捕获未处理异常并返回错误页面,这时中间件加的 CORS 头就丢了——所以 401/422/500 响应依然跨域失败。得在 render() 方法里也补一遍头,或者统一用异常响应格式封装。











