讲解如何在PHP中实现跨域资源共享(CORS)支持

轻松搞定PHP中的跨域资源共享(CORS)支持:一场技术讲座

各位同学,大家好!今天咱们来聊聊一个让前端和后端程序员都头疼的问题——跨域资源共享(CORS)。如果你曾经在开发中遇到过类似“Access to XMLHttpRequest at ‘https://example.com/api‘ from origin ‘http://localhost:3000‘ has been blocked by CORS policy”的错误,那你一定会对今天的讲座感兴趣!


什么是CORS?

首先,我们得搞清楚CORS是什么。简单来说,CORS是一种浏览器安全机制,用于限制网页上的JavaScript代码只能访问与当前页面同源的资源。所谓“同源”,是指协议、域名和端口号都相同。如果不同源,浏览器就会阻止请求,这就是所谓的“跨域问题”。

举个例子:

  • 页面地址:http://example.com
  • 请求地址:http://api.example.com

因为域名不同,所以被认为是跨域请求。


为什么需要CORS?

如果没有CORS,恶意网站可能会通过JavaScript发送请求到银行网站,窃取用户的敏感信息。因此,浏览器默认会阻止跨域请求,除非服务器明确允许。


PHP如何实现CORS支持?

接下来,我们就用PHP来解决这个问题。别担心,这并不复杂!下面我们分几步讲解。


第一步:理解HTTP头

CORS的核心是通过HTTP头来控制跨域请求。常见的CORS相关头有以下几个:

HTTP头 描述
Access-Control-Allow-Origin 指定哪些来源可以访问资源,值可以是具体域名或通配符*
Access-Control-Allow-Methods 指定允许的HTTP方法,例如GET, POST, PUT等。
Access-Control-Allow-Headers 指定允许的自定义请求头。
Access-Control-Allow-Credentials 是否允许携带身份验证信息(如Cookie)。
Access-Control-Max-Age 预检请求的结果缓存时间,单位为秒。

第二步:简单的CORS实现

假设你有一个API接口,希望允许任何来源访问它。可以在PHP文件的顶部添加以下代码:

<?php
// 允许所有来源访问
header("Access-Control-Allow-Origin: *");

// 允许的HTTP方法
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");

// 允许的请求头
header("Access-Control-Allow-Headers: Content-Type, Authorization");

// 如果是预检请求,直接返回200状态码
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}

// 正常处理请求
echo json_encode(['message' => 'Hello, World!']);

第三步:限制特定来源

如果你想只允许特定来源访问你的API,可以将Access-Control-Allow-Origin设置为具体的域名。例如:

<?php
$allowedOrigins = ['http://example.com', 'https://subdomain.example.com'];

// 获取请求来源
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';

// 检查来源是否在允许列表中
if (in_array($origin, $allowedOrigins)) {
    header("Access-Control-Allow-Origin: $origin");
} else {
    header("HTTP/1.1 403 Forbidden");
    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");

// 处理请求
echo json_encode(['message' => 'Hello, Secure World!']);

第四步:处理带凭证的请求

如果需要支持跨域请求时携带Cookie或身份验证信息,必须设置Access-Control-Allow-Credentialstrue。但要注意,设置了这个选项后,Access-Control-Allow-Origin不能使用通配符*,必须指定具体域名。

<?php
$allowedOrigin = 'http://example.com';

// 设置允许的来源
header("Access-Control-Allow-Origin: $allowedOrigin");

// 允许携带凭证
header("Access-Control-Allow-Credentials: true");

// 允许的HTTP方法
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");

// 允许的请求头
header("Access-Control-Allow-Headers: Content-Type, Authorization");

// 处理预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}

// 处理请求
echo json_encode(['message' => 'Hello with Credentials!']);

第五步:优化性能——预检请求缓存

对于复杂的跨域请求(如包含自定义头或非简单方法),浏览器会先发送一个预检请求(OPTIONS)。为了减少重复的预检请求,可以通过Access-Control-Max-Age设置缓存时间。

<?php
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"); // 缓存时间为1天

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}

echo json_encode(['message' => 'Hello with Cache!']);

总结

好了,今天的讲座到这里就结束了!我们学习了如何在PHP中实现CORS支持,包括以下几个关键点:

  1. 理解CORS的基本原理和常见HTTP头。
  2. 使用PHP设置跨域头,允许所有来源或特定来源访问。
  3. 处理带凭证的请求。
  4. 优化预检请求的性能。

虽然CORS看起来有点复杂,但只要掌握了这些技巧,就能轻松应对各种跨域问题。最后提醒一下,CORS配置不当可能会带来安全风险,所以在实际项目中一定要谨慎设置哦!

如果有任何疑问,欢迎在评论区留言!下次见啦,拜拜~

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注