laravel 11 需在 config/cors.php 中明确配置 cdn 前端域名到 allowed_origins(禁用 '*'),启用 supports_credentials,确保 paths 覆盖 api 路由,并在 api 中间件组注册 handlecors;cdn 层须禁止缓存 options 请求。

Laravel 11 本身不直接“配置 CDN”,但当你使用 CDN(如 Cloudflare、CloudFront 或自建 Nginx 反向代理)分发前端静态资源(如 Vue/React 构建产物),而 Laravel 后端 API 仍部署在独立域名(如 api.example.com)时,CORS 配置的关键是让 Laravel 正确响应来自 CDN 域名(如 https://cdn.example.com 或 https://your-app.vercel.app)的跨域请求。
CDN 本身不处理你的 Laravel 应用逻辑,它只是缓存并转发请求。所以 CORS 的责任仍在 Laravel 服务端 —— 你需要把 CDN 的前端域名明确加入 allowed_origins,而不是配 CDN 工具本身。
以下是具体操作要点:
✅ 明确允许 CDN 前端域名(不是通配符)
在 config/cors.php 中,将 allowed_origins 设为实际的前端访问地址,例如:
'allowed_origins' => [
'https://cdn.example.com',
'https://www.example.com',
'https://staging.example.com',
],
⚠️ 不要写 '*'(尤其生产环境):
CDN 域名通常固定且可预测,* 会禁用 credentials(如 Cookie、Authorization),导致登录态无法传递;同时违反安全最佳实践。
✅ 确保 supports_credentials 与 origins 匹配
如果你的前端通过 fetch(..., { credentials: 'include' }) 发送带 Cookie 的请求(比如 Laravel Sanctum 登录后调用 API),必须同时满足:
'supports_credentials' => true-
'allowed_origins'*不能含 ``**,必须是精确域名列表(如上) - 前端请求头中
Origin必须完全匹配(协议 + 域名 + 端口)
例如:前端从
https://cdn.example.com发起请求,Origin就是这个值,Laravel 才会返回Access-Control-Allow-Origin: https://cdn.example.com和Access-Control-Allow-Credentials: true。
✅ 路径配置需覆盖 API 入口
确保 config/cors.php 中的 'paths' 包含你实际使用的 API 路由前缀,常见配置:
'paths' => ['api/*', 'sanctum/csrf-cookie'],
若你用 /v1/users 这类路径,也建议加入 'v1/*' 或保持 'api/*' 并统一 API 前缀。
✅ 检查中间件注册位置(Laravel 11 推荐方式)
Laravel 11 默认已集成 fruitcake/laravel-cors(v4+),无需手动安装。确认以下两点:
-
config/cors.php已存在(首次运行php artisan vendor:publish --tag=cors生成) - 在
app/Http/Kernel.php的$middlewareGroups['api']中已包含:\Fruitcake\Cors\HandleCors::class,
✅ 推荐只加在
api组,避免影响 Web 页面(如 Blade 渲染的 HTML 页面不需要 CORS 头)
✅ CDN 缓存注意:不要缓存 OPTIONS 预检请求
这是容易被忽略的关键点:
- 浏览器对
POST/PUT/DELETE等非简单请求,会先发一个OPTIONS预检请求。 - 如果 CDN 错误地缓存了
OPTIONS响应(比如 200 + CORS 头),后续真实请求可能因缓存头不匹配失败。
✅ 正确做法(以 Cloudflare 为例):
- 在 Rules → HTTP Response Header 中,为
OPTIONS请求添加:Cache-Control: no-store, must-revalidate
- 或在 Nginx CDN 层配置:
if ($request_method = 'OPTIONS') { add_header Cache-Control "no-store, must-revalidate" always; add_header Access-Control-Allow-Origin "$http_origin" always; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always; add_header Access-Control-Allow-Headers "Content-Type, Authorization" always; add_header Access-Control-Allow-Credentials "true" always; return 204; }
不复杂但容易忽略。











