PHP跨域靠响应头控制而非密钥,密钥校验属业务层且须在CORS通过后执行;需正确设置Access-Control-Allow-Origin、Credentials等头,并避免输出干扰、服务器覆盖及CDN缓存问题。

PHP 跨域接口本身不需要“密钥”来实现跨域,CORS 是浏览器行为,靠响应头控制,不是靠密钥鉴权;如果你需要的是「带身份校验的跨域 API」,那密钥应放在请求头或参数里,由 PHP 后端自行验证,和跨域设置无关。
为什么加密钥不能解决跨域问题
浏览器在发起跨域请求时,会先发 OPTIONS 预检请求,只看响应头中是否有 Access-Control-Allow-Origin 等字段。它不检查你有没有传 api_key、也不管你用没用密钥解密——这些全是后端业务逻辑,发生在预检通过之后。
-
Access-Control-Allow-Origin: *允许任意域名跨域(但此时不能带凭证) -
Access-Control-Allow-Credentials: true允许带 Cookie 或认证头,但Access-Control-Allow-Origin不能为*,必须写具体域名 - 密钥校验(如
Authorization: Bearer xxx或X-API-Key: abc123)属于业务层,应在 CORS 头通过后再做
PHP 设置基础跨域响应头的写法
在输出任何内容前,用 header() 设置必要头。注意顺序和条件:如果接口要支持 Cookie 或 Token,必须显式允许凭证。
// 允许指定来源(开发环境可临时用 $_SERVER['HTTP_ORIGIN'] 动态匹配)
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
$allowed_origins = ['https://a.com', 'https://b.net'];
if (in_array($origin, $allowed_origins)) {
header("Access-Control-Allow-Origin: $origin");
header('Access-Control-Allow-Credentials: true');
}
// 允许的请求方法和头
header('Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-API-Key, X-Requested-With');
// 处理预检请求直接退出,不执行后续逻辑
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
exit(0);
}
如何安全地校验接口密钥(非跨域部分)
密钥验证必须独立于 CORS 设置,且建议放在统一入口或中间件里。常见错误是把密钥校验写在 CORS 头之前,导致未授权请求也能拿到跨域许可。
立即学习“PHP免费学习笔记(深入)”;
- 推荐从
Authorization请求头读取 Bearer Token:getallheaders()['Authorization'] ?? '' - 若用自定义头如
X-API-Key,需确保已在Access-Control-Allow-Headers中声明 - 密钥不应硬编码,建议从环境变量读取:
$_ENV['API_KEY']或getenv('API_KEY') - 验证失败时,仍要返回正确 CORS 头(否则浏览器可能报错“不允许的响应头”),再返回
401
容易被忽略的坑
最常踩的不是逻辑错,而是响应顺序和缓存干扰:
- 任何
echo、var_dump、空格或 BOM 字符出现在header()前,都会导致头发送失败 - Apache 的
mod_headers或 Nginx 的add_header可能覆盖 PHP 设置的 CORS 头,优先查服务器配置 - 某些 CDN(如 Cloudflare)默认缓存 OPTIONS 请求,导致预检失败;需设置缓存规则跳过
OPTIONS -
Access-Control-Max-Age设太大(如 86400),会让浏览器长期复用预检结果,改了后端头也不生效











