本文目录导读:

在 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]
重要提示
-
安全性考虑:
- 生产环境不要使用
Access-Control-Allow-Origin: *,应指定具体的域名 - 限制允许的请求方法和请求头
- 生产环境不要使用
-
预检请求缓存:
- 设置
Access-Control-Max-Age可以减少预检请求次数 - 值以秒为单位,建议设为 86400(24小时)
- 设置
-
常见问题:
- 如果使用自定义请求头(如 Authorization),必须使用预检请求
- 如果前端请求包含
credentials: 'include',后端必须设置Access-Control-Allow-Credentials: true,且不能使用
-
调试建议:
- 使用浏览器的开发者工具查看 Network 请求
- 检查预检请求和实际请求的响应头
选择哪种方式取决于你的项目架构和需求,对于简单的 API,使用第一种方式就足够了;对于复杂的应用,推荐使用中间件方式进行统一管理。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播