Laravel跨域失败主因是HandleCors中间件未注册、路由未命中API组或supports_credentials与allowed_origins冲突;需手动注册中间件、明确配置域名、避免通配符、校验预检请求。

直接上结论:Laravel 跨域问题不是改个 config/cors.php 就能解决的,90% 的失败案例卡在中间件没注册、路由没命中、或 supports_credentials 和 allowed_origins 配置冲突这三处。
为什么装了 fruitcake/laravel-cors 还报错 “No 'Access-Control-Allow-Origin' header”
核心原因:包已安装,但中间件根本没执行。Laravel 不会自动启用它,哪怕你改了配置文件也白搭。
-
fruitcake/laravel-cors的HandleCors中间件必须显式注册到app/Http/Kernel.php的$middleware(全局)或$middlewareGroups['api'](仅 API 路由)中;只放config/cors.php不起作用 - 检查你的请求 URL 是否真走的是
api/*路由 —— 如果写在routes/web.php里且没加->middleware('api'),HandleCors压根不会运行 - Laravel 9.2+ 虽默认集成该逻辑,但中间件仍需手动加入
$middlewareGroups['api'],默认值未必开启(尤其升级项目) - 运行
php artisan config:clear对 CORS 配置无效,因为它是运行时读取,不是 Laravel config 缓存体系的一部分
allowed_origins 设为 ['*'] 却提示 credentials error
这是典型的安全配置误用:只要 supports_credentials 为 true(比如前端带 withCredentials: true),allowed_origins 就绝不能是 ['*'],浏览器会直接拒绝响应。
- 必须明确列出前端域名,例如
['https://myapp.com', 'http://localhost:3000'] -
allowed_origins支持数组,不支持通配符子域名(如'https://*.example.com'),需手动枚举 - 若需动态匹配(如多租户前端),得改用自定义中间件,在
handle()里做$request->headers->get('Origin')白名单校验,再 set 头 -
supports_credentials同时影响Access-Control-Allow-Credentials响应头和 Cookie 传递,漏配会导致登录态无法同步
OPTIONS 预检请求返回 405 或空响应
浏览器发 OPTIONS 请求被拒,通常不是 CORS 配置问题,而是路由或中间件顺序导致预检未被捕获。
-
HandleCors中间件必须放在认证类中间件(如Authenticate、EnsureTokenIsValid)之前,否则未登录用户连预检都过不去 -
allowed_methods别设成['*']:某些 CDN、Nginx 或反向代理会拦截含Access-Control-Allow-Methods: *的响应,建议显式写全,如['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'] - 确认
paths配置覆盖了预检路径,例如'paths' => ['api/*']要求请求路径以/api/开头;若用sanctum/csrf-cookie,也得加进去 - 如果用 Nginx,确保没用
limit_except或其他规则直接拒绝OPTIONS方法
生产环境 CORS 安全红线
开发时用 ['*'] 图省事,上线后就是漏洞入口。真正要守住的只有两点:
-
allowed_origins必须锁定具体域名,禁止通配符;可通过.env注入,如CORS_ALLOWED_ORIGINS=https://app.example.com,https://admin.example.com,并在config/cors.php中用explode(',', env('CORS_ALLOWED_ORIGINS', ''))解析 -
exposed_headers若前端 JS 需读取自定义响应头(如X-RateLimit-Remaining),必须在这里显式声明,否则 JS 拿不到 - 别依赖前端传来的
Origin头做反射式回写——除非你有强校验逻辑,否则等于开放任意域调用


















