PHPAPI跨域怎么配置

wen PHP项目 2

本文目录导读:

PHPAPI跨域怎么配置

  1. 核心响应头
  2. 简单跨域配置
  3. 完整跨域配置(推荐)
  4. 使用中间件模式
  5. Nginx 代理配置(推荐用于生产)
  6. Apache .htaccess 配置
  7. 常见问题与解决
  8. 安全建议

在 PHP 中配置跨域 (CORS, Cross-Origin Resource Sharing),通常需要在服务端返回特定的 HTTP 响应头,以下是几种常见场景的配置方法。

核心响应头

// 最基本的3个响应头
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');

简单跨域配置

<?php
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json; charset=utf-8');
// 你的API逻辑
echo json_encode(['message' => 'Hello World']);

完整跨域配置(推荐)

<?php
// 允许访问的域名(生产环境建议指定具体域名)
$allowedOrigins = [
    'http://localhost:3000',
    'https://example.com',
];
// 获取请求来源
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
// 验证来源
if (in_array($origin, $allowedOrigins)) {
    header('Access-Control-Allow-Origin: ' . $origin);
    header('Access-Control-Allow-Credentials: true'); // 允许携带凭证(cookies)
}
// 设置允许的请求方法
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, PATCH');
// 设置允许的请求头
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
// 设置预检请求缓存时间(秒)
header('Access-Control-Max-Age: 86400');
// 处理预检请求 (OPTIONS)
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}
// 你的API逻辑
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['status' => 'success']);

使用中间件模式

<?php
class CorsMiddleware {
    public static function handle() {
        // 允许的来源
        $allowedOrigins = ['http://localhost:3000'];
        $origin = $_SERVER['HTTP_ORIGIN'] ?? '';
        if (in_array($origin, $allowedOrigins)) {
            header('Access-Control-Allow-Origin: ' . $origin);
            header('Access-Control-Allow-Credentials: true');
        }
        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;
        }
    }
}
// 使用
CorsMiddleware::handle();
// 后续的API逻辑...

Nginx 代理配置(推荐用于生产)

有时候在 Nginx 层配置更灵活:

server {
    listen 80;
    server_name api.example.com;
    location / {
        # 允许跨域
        add_header Access-Control-Allow-Origin * always;
        add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
        add_header Access-Control-Allow-Headers 'Content-Type, Authorization';
        add_header Access-Control-Max-Age 86400;
        # 处理OPTIONS请求
        if ($request_method = 'OPTIONS') {
            add_header Content-Length 0;
            add_header Content-Type text/plain;
            return 204;
        }
        # 代理到PHP-FPM
        try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

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"
</IfModule>
# 处理OPTIONS请求
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]

常见问题与解决

问题1:跨域请求带Cookie

header('Access-Control-Allow-Origin: https://specific-domain.com'); // 不能使用*
header('Access-Control-Allow-Credentials: true');

问题2:自定义请求头

// 客户端设置自定义头
headers: {
    'X-Custom-Header': 'value'
}
// 服务端必须允许
header('Access-Control-Allow-Headers: X-Custom-Header');

问题3:文件上传跨域

header('Access-Control-Allow-Headers: Content-Type');
// 确保Content-Type被允许

问题4:多个域名支持

$allowedOrigins = [
    'http://localhost:3000',
    'https://example.com',
    'https://subdomain.example.com'
];
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, $allowedOrigins)) {
    header('Access-Control-Allow-Origin: ' . $origin);
} else {
    header('Access-Control-Allow-Origin: ' . $allowedOrigins[0]);
}

安全建议

  1. *生产环境不要用 ``**,指定具体的域名
  2. 验证请求来源,避免恶意跨域
  3. 设置合理的 Access-Control-Max-Age,减少预检请求
  4. 只开放必要的请求方法(需要哪些就开放哪些)
  5. 敏感API需要结合其他认证措施(如JWT token)

选择哪种方式取决于你的项目架构和部署环境,对于简单项目,直接在PHP文件开头添加CORS头即可;对于大型项目推荐使用中间件模式或反向代理配置。

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