PHPAPICORS预检怎么处理

wen PHP项目 2

本文目录导读:

PHPAPICORS预检怎么处理

  1. 简单处理方式(适用于单文件 API)
  2. 使用中间件方式(适用于框架)
  3. 更灵活的处理方式(支持动态域名)
  4. 完整的 API 入口文件示例
  5. 使用 .htaccess 文件(Apache 服务器)
  6. 重要提示

在 PHP API 中处理 CORS 预检请求(OPTIONS 请求),通常需要在后端添加对应的响应头,以下是几种常见的处理方式:

简单处理方式(适用于单文件 API)

<?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");
// 处理预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    // 预检请求缓存时间(秒)
    header("Access-Control-Max-Age: 86400");
    http_response_code(204); // 无内容响应
    exit;
}
// 您的正常 API 逻辑
// ...
?>

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

<?php
class CorsMiddleware {
    public function handle() {
        header("Access-Control-Allow-Origin: *");
        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(204);
            exit;
        }
    }
}
// 使用
$cors = new CorsMiddleware();
$cors->handle();
?>

更灵活的处理方式(支持动态域名)

<?php
/**
 * 处理 CORS 预检请求
 * @param array $allowedOrigins 允许的域名列表
 * @param array $allowedMethods 允许的方法
 * @param array $allowedHeaders 允许的头信息
 */
function handleCors(
    array $allowedOrigins = ['*'],
    array $allowedMethods = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
    array $allowedHeaders = ['Content-Type', 'Authorization', 'X-Requested-With']
) {
    // 获取请求来源
    $origin = $_SERVER['HTTP_ORIGIN'] ?? '*';
    // 检查来源是否允许
    if (in_array('*', $allowedOrigins) || in_array($origin, $allowedOrigins)) {
        header("Access-Control-Allow-Origin: " . (in_array('*', $allowedOrigins) ? '*' : $origin));
        header("Access-Control-Allow-Methods: " . implode(', ', $allowedMethods));
        header("Access-Control-Allow-Headers: " . implode(', ', $allowedHeaders));
        header("Access-Control-Max-Age: 86400");
        // 处理凭据(如果需要)
        if (in_array('*', $allowedOrigins)) {
            // 如果允许所有来源,不能设置凭据
        } else {
            header("Access-Control-Allow-Credentials: true");
        }
        // 处理预检请求
        if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
            http_response_code(204);
            exit;
        }
    }
}
// 使用示例
handleCors();
// 或者限制特定域名
// handleCors(['https://example.com', 'https://app.example.com']);
?>

完整的 API 入口文件示例

<?php
// api.php - API 入口文件
// 配置
$config = [
    'allowed_origins' => ['*'],
    'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
    'allowed_headers' => ['Content-Type', 'Authorization', 'X-Requested-With', 'Accept'],
    'max_age' => 86400 // 24小时
];
// 处理 CORS
$origin = $_SERVER['HTTP_ORIGIN'] ?? '*';
if ($origin === '*' || in_array($origin, $config['allowed_origins'])) {
    header("Access-Control-Allow-Origin: " . $config['allowed_origins'][0] === '*' ? '*' : $origin);
    header("Access-Control-Allow-Methods: " . implode(', ', $config['allowed_methods']));
    header("Access-Control-Allow-Headers: " . implode(', ', $config['allowed_headers']));
    header("Access-Control-Max-Age: " . $config['max_age']);
    // 需要处理凭据时
    if ($origin !== '*') {
        header("Access-Control-Allow-Credentials: true");
    }
    // 预检请求处理
    if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
        http_response_code(204);
        exit;
    }
}
// 设置响应类型
header('Content-Type: application/json');
// API 路由逻辑
$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
switch(true) {
    case $path === '/api/users' && $method === 'GET':
        // 获取用户列表
        echo json_encode(['users' => []]);
        break;
    case $path === '/api/users' && $method === 'POST':
        // 创建用户
        echo json_encode(['message' => 'User created']);
        break;
    default:
        http_response_code(404);
        echo json_encode(['error' => 'Not found']);
}
?>

使用 .htaccess 文件(Apache 服务器)

如果使用 Apache 服务器,也可以在 .htaccess 文件中配置:

<IfModule mod_headers.c>
    # 允许所有来源
    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, X-Requested-With"
    # 预检请求缓存时间
    Header set Access-Control-Max-Age "86400"
</IfModule>
# 处理 OPTIONS 预检请求
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=204,L]

重要提示

  1. 安全性考虑

    • 生产环境不要使用 Access-Control-Allow-Origin: *,应指定具体的域名
    • 限制允许的请求方法和请求头
  2. 预检请求缓存

    • 设置 Access-Control-Max-Age 可以减少预检请求次数
    • 值以秒为单位,建议设为 86400(24小时)
  3. 常见问题

    • 如果使用自定义请求头(如 Authorization),必须使用预检请求
    • 如果前端请求包含 credentials: 'include',后端必须设置 Access-Control-Allow-Credentials: true,且不能使用
  4. 调试建议

    • 使用浏览器的开发者工具查看 Network 请求
    • 检查预检请求和实际请求的响应头

选择哪种方式取决于你的项目架构和需求,对于简单的 API,使用第一种方式就足够了;对于复杂的应用,推荐使用中间件方式进行统一管理。

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