Laravel 9 CORS详解:跨域资源共享终极指南
2024-12-29 19:13:55
Laravel 9 中跨域资源共享(CORS)问题详解
在前后端分离的架构中,跨域资源共享(CORS)问题非常常见。当浏览器从一个源(域名、协议或端口)向另一个源发起请求时,会受到浏览器的同源策略限制。例如,Vue.js前端应用(运行于http://127.0.0.1:8080
)尝试向Laravel 9 API后端服务(运行于http://localhost:8000
)发送请求,此时浏览器就可能会抛出CORS错误。 本文将探讨此问题的根本原因并给出可行的解决方案。
问题
浏览器控制台会显示类似下面的错误:
Access to XMLHttpRequest at 'http://localhost:8000/api' from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
这个错误清楚地表明,服务器端的响应头中缺少 Access-Control-Allow-Origin
字段,浏览器据此判断此跨域请求是被禁止的。
原因分析
出现这个问题的根本原因是,默认情况下,服务器响应不会携带CORS相关的头部信息。即使Laravel应用中有默认的config/cors.php
配置,但仅仅依靠此配置文件是不够的。配置仅决定允许哪些源、方法和头部,实际生效仍需要中间件配合。默认的配置没有添加cors中间件,所以服务器发送的响应不会带有 Access-Control-Allow-Origin
等头信息。
解决方案
解决 CORS 问题通常涉及修改服务端响应的头部信息,让浏览器信任这个跨域请求。以下提供多种解决策略。
1. 添加全局 CORS 中间件
Laravel 提供 fruitcake/laravel-cors
包来实现 CORS 配置,并可以将其添加到全局中间件,保证每个API响应都有 CORS 相关头。
步骤:
-
安装
fruitcake/laravel-cors
包:composer require fruitcake/laravel-cors
-
打开
app/Http/Kernel.php
, 将\Fruitcake\Cors\HandleCors::class
添加到$middlewarePriority
数组。
protected $middlewarePriority = [
...
\Fruitcake\Cors\HandleCors::class, // 添加这行
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Auth\Middleware\Authenticate::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class,
\Illuminate\Http\Middleware\HandlePreflight::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
];
此后,所有的API响应都会附加CORS相关的头部信息,允许你的前端访问API资源。这种方式简单高效,尤其在需要处理多路由CORS请求的时候。
2. 配置 CORS 文件 cors.php
如果使用了 fruitcake/laravel-cors
包, 则配置文件在 config/cors.php
. 你可以在这里指定哪些域允许访问你的后端 API。
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['http://127.0.0.1:8080'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];
paths
: 指定哪些路由应用 CORS 规则,可以使用通配符,如'api/*'
,表示api/
目录下的所有路由。'sanctum/csrf-cookie'
是 Laravel Sanctum 认证时的路由,建议保留。allowed_methods
: 允许的 HTTP 请求方法,'*'
表示允许所有。可以配置'GET'
,'POST'
,'PUT'
,'DELETE'
等。allowed_origins
: 允许访问 API 的源。指定特定的域名或者使用'*'
,允许所有。出于安全考虑,通常不建议使用*
,应该明确指定可以跨域访问你的 API 的域名列表。allowed_origins_patterns
: 使用正则表达式匹配来源。这个设置允许使用更加复杂的域名规则。allowed_headers
: 允许客户端携带的头部信息,*
表示允许所有。exposed_headers
: 允许客户端访问的响应头部信息。max_age
: 预检请求的缓存时间。supports_credentials
: 是否允许客户端携带credentials
,通常用于允许Cookie
跨域。
修改此配置文件之后, 建议使用 php artisan config:cache
清理配置缓存。
3. 修改 Nginx 或 Apache 配置(服务器层面)
对于部署在 Nginx 或 Apache 等 web 服务器上的 Laravel 项目,也可以在服务器配置层面直接添加 CORS 相关的头部。这样做能够更快地解决问题,因为它不依赖于PHP应用程序的处理。
示例(Nginx):
在你的 server 配置中,可以加入以下配置:
server {
...
location / {
...
add_header 'Access-Control-Allow-Origin' 'http://127.0.0.1:8080';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
}
# 对于 OPTIONS 方法请求的特别处理
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'http://127.0.0.1:8080';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Content-Type' 'application/json; charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
注意: 需要将 'http://127.0.0.1:8080'
修改为你实际的前端访问域名。修改后重启 Nginx 服务器使其生效。类似的操作,也适用与 Apache。
总结与建议
- 最常用的方法是使用
fruitcake/laravel-cors
中间件配合配置文件,能提供更灵活的管理方式。 - 仅使用配置文件的cors设置并不生效,必须同时启用相应的中间件。
- 尽量在服务器端解决 CORS 问题,能减少代码依赖和提高效率。
- 明确允许的域名,避免在生产环境使用
*
作为allowed_origins
的值。
通过实施上述方案中的一种或几种,即可有效解决 Laravel 9 应用中遇到的 CORS 问题。 在开发中灵活应用,可以高效构建可靠的 API 服务。