PHP项目AJAX请求如何跨域处理

wen PHP项目 29

本文目录导读:

PHP项目AJAX请求如何跨域处理

  1. 服务端设置CORS(推荐)
  2. Nginx配置CORS
  3. Apache配置CORS
  4. JSONP方式(仅支持GET请求)
  5. 代理转发(开发环境)
  6. PHP CORS中间件封装
  7. 前端AJAX请求示例
  8. 注意事项

在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);
});

注意事项

  1. 安全考虑:生产环境不要使用 Access-Control-Allow-Origin: *,应该指定具体的域名
  2. 凭证传递:如果需要传递Cookie,必须设置 Access-Control-Allow-Credentials: true
  3. 预检请求:复杂请求(如使用自定义Header或非简单方法)会先发送OPTIONS预检请求
  4. 浏览器兼容性:CORS需要现代浏览器支持,JSONP兼容性更好但功能有限

建议优先使用服务端CORS配置,这是最标准、最安全的跨域解决方案。

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