本文目录导读:

- 基础CORS设置(允许所有来源)
- 指定特定域名(推荐生产环境)
- 支持携带凭证(Cookie/认证信息)
- 使用中间件方式(适用于框架)
- 使用.htaccess配置(Apache服务器)
- 常见问题及解决方案
- 完整示例(通用方案)
在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();
根据你的具体需求选择合适的方案,生产环境建议使用白名单方式限制来源域名,以提高安全性。