cors中间件未生效的主因是注册顺序错误或配置冲突;需将其置于路由中间件之后、依赖session/cookie中间件之前,且allowed_origins不可设为['*'](否则禁用凭证),并确保options预检路由存在且未被认证中间件拦截。

为什么 Cors 中间件没生效?检查中间件注册顺序
中间件顺序错了,Cors 就永远追不上请求——它必须在路由匹配之后、控制器执行之前运行,但又不能晚于 StartSession 或 EncryptCookies 这类依赖 session/cookie 的中间件。
- 在
app/Http/Kernel.php的$middlewareGroups['web']或$middlewareGroups['api']里,把\Fruitcake\Cors\HandleCors::class往前放,建议紧挨着\App\Http\Middleware\EncryptCookies::class后面 - 别把它塞进全局
$middleware数组——那样会对所有请求(包括静态资源、健康检查)加 CORS 头,徒增干扰 - 如果用了自定义中间件做鉴权或日志,确认它们没提前
return或抛出异常,否则Cors根本没机会执行
配置 cors.allowed_origins 时,* 不等于“全放行”
设成 ['*'] 看似省事,但会直接让浏览器拒绝带凭证(如 cookies、Authorization header)的请求——这是浏览器的硬性限制,Laravel 挡不住,也改不了。
- 需要传 cookie 或 token?必须显式列出可信域名:
['https://myapp.com', 'http://localhost:3000'] - 开发环境用
http://localhost:*不行,通配符只支持完整域名或*,不支持端口通配;建议本地开发时写死http://localhost:3000 -
cors.supports_credentials必须设为true,且前端 fetch 要加credentials: 'include',两者缺一不可
OPTIONS 预检请求 405 错误?确认路由没被中间件拦截
Laravel 默认不会为 OPTIONS 请求匹配路由,所以预检失败常是因为中间件链里某个环节直接返回了 405(Method Not Allowed),而不是因为 CORS 配置错。
- 检查是否在
routes/api.php里漏写了对应路由——哪怕只是空的Route::options('/api/foo', fn() => response(''));,也要有,否则 Laravel 无法响应预检 - 确保该路由没被
auth:sanctum或其他需要认证的中间件包裹,预检请求不含 token,认证中间件会直接拒掉 - 如果用的是 API 路由组,确认
api中间件组已启用Cors,不是只配在web组里
调试时看哪几个响应头?别只盯 Access-Control-Allow-Origin
一个完整的跨域响应至少要凑齐三样:源、方法、凭证支持。少一个,前端照样报错,而且错误信息往往只提第一个失败项。
- 用
curl -I -X OPTIONS http://your.app/api/endpoint看响应头,重点检查:Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers、Access-Control-Allow-Credentials -
Access-Control-Allow-Headers如果没包含前端实际发的 header(比如X-Requested-With或自定义X-Api-Key),预检就过不去;在配置里补全:'allowed_headers' => ['*']或明确列出 - 注意:Laravel 9+ 默认禁用
Access-Control-Allow-Credentials,即使你开了supports_credentials,也得确保allowed_origins是具体域名,不能是*
真正卡住的地方,往往是预检请求没走通,或者凭证开关和允许源冲突——这两个点查不到日志,只能靠 curl 和浏览器 Network 面板对着头一个个比对。











