本文目录导读:

在PHP项目中处理AJAX跨域请求,主要有以下几种解决方案:
服务端设置CORS(推荐)
基础CORS设置
在PHP文件头部添加:
<?php
// 允许所有域名访问(开发环境)
header('Access-Control-Allow-Origin: *');
// 或允许特定域名
header('Access-Control-Allow-Origin: https://example.com');
// 设置允许的请求方法
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
// 设置允许的请求头
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
// 允许携带凭证(如Cookie)
header('Access-Control-Allow-Credentials: true');
// 预检请求缓存时间(秒)
header('Access-Control-Max-Age: 86400');
?>
完整跨域处理示例
<?php
// 跨域处理函数
function handleCORS() {
// 允许的域名列表
$allowedOrigins = [
'https://example.com',
'https://www.example.com',
'http://localhost:3000'
];
// 获取请求来源
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
// 检查是否允许访问
if (in_array($origin, $allowedOrigins)) {
header("Access-Control-Allow-Origin: $origin");
header('Access-Control-Allow-Credentials: true');
} else {
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');
header('Access-Control-Max-Age: 86400');
// 处理预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit();
}
}
// 调用跨域处理
handleCORS();
// 实际业务逻辑
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
// 处理数据...
echo json_encode(['status' => 'success', 'data' => $data]);
}
?>
Nginx配置CORS
在nginx配置文件中添加:
location /api/ {
# 允许跨域
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
add_header Access-Control-Allow-Headers 'Content-Type, Authorization, X-Requested-With';
add_header Access-Control-Max-Age 86400;
# 处理OPTIONS预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
add_header Access-Control-Allow-Headers 'Content-Type, Authorization, X-Requested-With';
add_header Access-Control-Max-Age 86400;
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
}
Apache配置CORS
在.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>
JSONP方式(仅支持GET请求)
PHP服务端
<?php
$callback = $_GET['callback'] ?? '';
$data = ['name' => '张三', 'age' => 25];
if ($callback) {
echo $callback . '(' . json_encode($data) . ')';
} else {
echo json_encode($data);
}
?>
前端AJAX请求
// jQuery方式
$.ajax({
url: 'http://api.example.com/data',
dataType: 'jsonp',
jsonp: 'callback',
success: function(data) {
console.log(data);
}
});
// 原生JS方式
function handleData(data) {
console.log(data);
}
var script = document.createElement('script');
script.src = 'http://api.example.com/data?callback=handleData';
document.body.appendChild(script);
代理转发(开发环境)
Vue项目(vue.config.js)
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
React项目(package.json或webpack配置)
{
"proxy": "http://localhost:8080"
}
PHP CORS中间件封装
创建一个可复用的CORS中间件:
<?php
class CORSMiddleware {
private $allowedOrigins = [];
private $allowedMethods = [];
private $allowedHeaders = [];
private $allowCredentials = false;
private $maxAge = 86400;
public function __construct($config = []) {
$this->allowedOrigins = $config['origins'] ?? ['*'];
$this->allowedMethods = $config['methods'] ?? ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'];
$this->allowedHeaders = $config['headers'] ?? ['Content-Type', 'Authorization', 'X-Requested-With'];
$this->allowCredentials = $config['credentials'] ?? false;
$this->maxAge = $config['maxAge'] ?? 86400;
}
public function handle() {
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
// 设置Access-Control-Allow-Origin
if (in_array('*', $this->allowedOrigins)) {
header('Access-Control-Allow-Origin: *');
} elseif (in_array($origin, $this->allowedOrigins)) {
header("Access-Control-Allow-Origin: $origin");
}
// 设置其他头信息
header('Access-Control-Allow-Methods: ' . implode(', ', $this->allowedMethods));
header('Access-Control-Allow-Headers: ' . implode(', ', $this->allowedHeaders));
header('Access-Control-Max-Age: ' . $this->maxAge);
if ($this->allowCredentials) {
header('Access-Control-Allow-Credentials: true');
}
// 处理预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit();
}
}
}
// 使用示例
$cors = new CORSMiddleware([
'origins' => ['https://example.com', 'http://localhost:3000'],
'methods' => ['GET', 'POST', 'PUT', 'DELETE'],
'headers' => ['Content-Type', 'Authorization'],
'credentials' => true
]);
$cors->handle();
?>
前端AJAX请求示例
// 使用fetch API
fetch('http://api.example.com/data', {
method: 'POST',
credentials: 'include', // 携带Cookie
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({name: '张三'})
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
// 使用axios
axios.post('http://api.example.com/data', {
name: '张三'
}, {
withCredentials: true // 携带Cookie
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error:', error);
});
注意事项
- 安全考虑:生产环境不要使用
Access-Control-Allow-Origin: *,应该指定具体的域名 - 凭证传递:如果需要传递Cookie,必须设置
Access-Control-Allow-Credentials: true - 预检请求:复杂请求(如使用自定义Header或非简单方法)会先发送OPTIONS预检请求
- 浏览器兼容性:CORS需要现代浏览器支持,JSONP兼容性更好但功能有限
建议优先使用服务端CORS配置,这是最标准、最安全的跨域解决方案。