PHP项目Laravel跨域资源共享配置

wen PHP项目 6

本文目录导读:

PHP项目Laravel跨域资源共享配置

  1. 方法1:使用Laravel内置CORS中间件(推荐)
  2. 方法2:自定义中间件
  3. 方法3:全局中间件(适用于所有请求)
  4. 方法4:控制器级别配置
  5. 方法5:路由组配置
  6. Nginx/Apache服务器配置
  7. 配置验证
  8. 注意事项

在Laravel项目中配置跨域资源共享(CORS)有几种方法,以下是完整的配置指南:

方法1:使用Laravel内置CORS中间件(推荐)

Laravel 9+ 默认包含CORS支持,Laravel 7/8需要安装扩展包。

安装(Laravel 7/8)

composer require fruitcake/laravel-cors

发布配置文件(所有版本)

php artisan vendor:publish --tag=cors

配置 config/cors.php

<?php
return [
    /*
    |--------------------------------------------------------------------------
    | Cross-Origin Resource Sharing (CORS) Configuration
    |--------------------------------------------------------------------------
    */
    'paths' => ['api/*', 'sanctum/csrf-cookie'], // 允许的路径
    'allowed_methods' => ['*'], // 允许的HTTP方法
    'allowed_origins' => ['*'], // 允许的来源(域名)
    'allowed_origins_patterns' => ['*'], // 允许来源的正则表达式
    'allowed_headers' => ['*'], // 允许的请求头
    'exposed_headers' => [], // 暴露给客户端的响应头
    'max_age' => 0, // 预检请求的缓存时间(秒)
    'supports_credentials' => false, // 是否允许携带认证信息(cookies等)
];

具体配置示例

<?php
return [
    'paths' => ['api/*', 'login', 'register'],
    'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
    'allowed_origins' => [
        'http://localhost:3000',
        'http://localhost:5173',
        'https://your-frontend.com',
    ],
    'allowed_origins_patterns' => [
        'http://*.example.com',
    ],
    'allowed_headers' => [
        'Content-Type',
        'X-Requested-With',
        'Authorization',
        'X-CSRF-TOKEN',
        'Origin',
        'Accept',
    ],
    'exposed_headers' => [
        'X-Pagination-Current-Page',
        'X-Pagination-Total',
    ],
    'max_age' => 3600,
    'supports_credentials' => true,
];

方法2:自定义中间件

如果需要对CORS进行更细粒度的控制,可以创建自定义中间件。

创建中间件

php artisan make:middleware Cors

中间件代码

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class Cors
{
    public function handle(Request $request, Closure $next)
    {
        // 处理预检请求
        if ($request->isMethod('OPTIONS')) {
            return response('', 200)
                ->header('Access-Control-Allow-Origin', '*')
                ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS')
                ->header('Access-Control-Allow-Headers', 'Content-Type, X-Requested-With, Authorization, X-CSRF-TOKEN');
        }
        // 处理其他请求
        $response = $next($request);
        $response->headers->set('Access-Control-Allow-Origin', '*');
        $response->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
        $response->headers->set('Access-Control-Allow-Headers', 'Content-Type, X-Requested-With, Authorization, X-CSRF-TOKEN');
        $response->headers->set('Access-Control-Max-Age', '3600');
        return $response;
    }
}

注册中间件

app/Http/Kernel.php 中:

protected $middlewareGroups = [
    'web' => [
        // ...
        \App\Http\Middleware\Cors::class,
    ],
    'api' => [
        // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        \App\Http\Middleware\Cors::class,
        'throttle:api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
];

方法3:全局中间件(适用于所有请求)

app/Http/Kernel.php 中添加全局中间件:

protected $middleware = [
    // ...
    \App\Http\Middleware\Cors::class,
];

方法4:控制器级别配置

在控制器构造函数或方法中设置:

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class UserController extends Controller
{
    public function getUser(Request $request)
    {
        $data = ['name' => 'John Doe'];
        return response()->json($data)
            ->header('Access-Control-Allow-Origin', '*')
            ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
            ->header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    }
}

方法5:路由组配置

<?php
use Illuminate\Support\Facades\Route;
Route::group(['middleware' => ['cors']], function () {
    Route::get('/api/users', 'UserController@index');
    Route::post('/api/users', 'UserController@store');
    // 其他需要CORS的路由
});

Nginx/Apache服务器配置

除了应用层配置,还需要确保服务器配置支持:

Nginx配置

location / {
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With';
        add_header 'Access-Control-Max-Age' '3600';
        return 204;
    }
    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With';
}

Apache配置

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
    Header set Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS"
    Header set Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With"
</IfModule>
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} OPTIONS
    RewriteRule ^(.*)$ $1 [R=200,L]
</IfModule>

配置验证

创建一个测试路由:

<?php
use Illuminate\Support\Facades\Route;
Route::options('/api/test-cors', function () {
    return response()->json([], 204);
});
Route::get('/api/test-cors', function () {
    return response()->json(['success' => true, 'message' => 'CORS配置成功']);
});

使用curl测试:

curl -H "Origin: http://localhost:3000" \
     -H "Access-Control-Request-Method: GET" \
     -X OPTIONS \
     http://your-app.test/api/test-cors -v

注意事项

  1. 安全性:生产环境建议只允许特定的域名,避免使用通配符
  2. 凭据:如果使用 cookies 或认证信息,设置 supports_credentialstrue
  3. 缓存:合理设置 max_age 减少预检请求次数
  4. 调试:使用浏览器的开发者工具检查CORS错误信息
  5. HTTPS:如果使用HTTPS,确保前端也是HTTPS协议

选择适合你项目的方法,建议使用Laravel内置的CORS配置(方法1),它提供了最灵活和安全的配置方式。

抱歉,评论功能暂时关闭!