PHP项目如何处理跨域请求报错?

wen PHP项目 8

本文目录导读:

PHP项目如何处理跨域请求报错?

  1. 基础CORS设置(允许所有来源)
  2. 指定特定域名(推荐生产环境)
  3. 支持携带凭证(Cookie/认证信息)
  4. 使用中间件方式(适用于框架)
  5. 使用.htaccess配置(Apache服务器)
  6. 常见问题及解决方案
  7. 完整示例(通用方案)

在PHP项目中处理跨域请求(CORS)报错,主要通过在服务器端设置相应的HTTP响应头来实现,以下是几种常见的解决方案:

基础CORS设置(允许所有来源)

在PHP文件开头添加以下代码:

<?php
// 允许所有来源访问
header('Access-Control-Allow-Origin: *');
// 允许的请求方法
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
// 允许的请求头
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
// 设置响应内容类型(如需返回JSON)
header('Content-Type: application/json; charset=utf-8');
// 处理预检请求(OPTIONS请求)
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    http_response_code(200);
    exit();
}

指定特定域名(推荐生产环境)

<?php
// 允许特定域名访问
$allowed_origins = [
    'http://localhost:3000',
    'https://yourdomain.com',
    'https://www.yourdomain.com'
];
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, $allowed_origins)) {
    header("Access-Control-Allow-Origin: $origin");
} else {
    // 如果来源不在白名单中,拒绝访问
    http_response_code(403);
    echo json_encode(['error' => 'Forbidden']);
    exit();
}
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Access-Control-Max-Age: 86400'); // 预检请求缓存时间(秒)
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    http_response_code(200);
    exit();
}

支持携带凭证(Cookie/认证信息)

当需要发送Cookie或认证信息时:

<?php
// 必须指定具体域名,不能使用*
header('Access-Control-Allow-Origin: http://localhost:3000');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    http_response_code(200);
    exit();
}

使用中间件方式(适用于框架)

Laravel 示例:

app/Http/Middleware/Cors.php:

<?php
namespace App\Http\Middleware;
use Closure;
class Cors
{
    public function handle($request, Closure $next)
    {
        return $next($request)
            ->header('Access-Control-Allow-Origin', '*')
            ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
            ->header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    }
}

使用.htaccess配置(Apache服务器)

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type, Authorization"
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]

常见问题及解决方案

问题1:预检请求(OPTIONS)返回405

// 确保处理OPTIONS请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
    header('Access-Control-Allow-Headers: Content-Type, Authorization');
    exit;
}

问题2:自定义请求头被拒绝

确保在 Access-Control-Allow-Headers 中包含所有自定义请求头:

header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Custom-Header');

问题3:多个域名需要支持

$allowed_origins = ['https://site1.com', 'https://site2.com'];
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, $allowed_origins)) {
    header("Access-Control-Allow-Origin: $origin");
}

完整示例(通用方案)

<?php
/**
 * 通用的CORS处理函数
 */
function handleCors() {
    // 允许的域名列表
    $allowed_origins = [
        'http://localhost:3000',
        'http://localhost:8080',
        'https://yourproductiondomain.com'
    ];
    $origin = $_SERVER['HTTP_ORIGIN'] ?? '';
    // 检查请求来源是否在允许列表中
    if (in_array($origin, $allowed_origins)) {
        header("Access-Control-Allow-Origin: $origin");
    } elseif (empty($origin)) {
        // 对于非浏览器请求(如curl),可能没有Origin头
        header('Access-Control-Allow-Origin: *');
    } else {
        // 拒绝未授权的来源
        http_response_code(403);
        echo json_encode(['error' => 'Origin not allowed']);
        exit();
    }
    // 设置CORS头
    header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
    header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');
    header('Content-Type: application/json; charset=utf-8');
    // 处理预检请求
    if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
        http_response_code(200);
        exit();
    }
}
// 在项目入口处调用
handleCors();

根据你的具体需求选择合适的方案,生产环境建议使用白名单方式限制来源域名,以提高安全性。

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