明明都是请求同一个接口,
AJAX 一直报跨域错误,PHP cURL 却能正常返回?
很多 PHP 新手、甚至工作几年的开发,都在这个问题上反复踩坑。
这篇文章,我用最直白的方式,一次把 PHP AJAX 跨域、PHP cURL 跨域、CORS、Session、Cookie 这些事讲清楚。
一、一个最常见的“诡异现象”
很多人遇到过这样的情况:
- 浏览器里用 AJAX 请求接口
❌ 控制台直接报错:
No 'Access-Control-Allow-Origin' header - 服务器里用 PHP cURL 请求同一个接口
✅ 返回正常,数据齐全
于是问题来了:
接口明明没问题,为什么 AJAX 不行,cURL 却行?
答案只有一句话,但90%的人没意识到:
AJAX 会被浏览器限制,cURL 不会。
下面一步步拆开讲。
二、根本区别:谁在“发请求”?
1️⃣ PHP AJAX:请求是“浏览器发的”
$.ajax({
url: "https://api.example.com/user",
type: "GET",
success(res) {
console.log(res)
}
})
👉 本质是:
- 请求由 浏览器 发出
- 浏览器会 强制执行同源策略(Same-Origin Policy)
- 只要跨域,就要检查 CORS 响应头
浏览器一句话原则:
后端没允许跨域,我就不让你拿数据
2️⃣ PHP cURL:请求是“服务器发的”
$ch = curl_init("https://api.example.com/user");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($ch);
👉 本质是:
- 请求由 服务器 发出
- 没有浏览器
- 不存在跨域限制
- 也就 不看 CORS
所以:
PHP cURL 天生“无视跨域”
三、为什么 AJAX 必须配置 CORS?
浏览器跨域时会检查这些响应头 👇
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Allow-Credentials
只要少一个,或者配置错误:
- AJAX 请求 ❌
- 控制台直接拦截
- 后端日志甚至看不到请求
四、AJAX 跨域最容易踩的 4 个坑
❌ 坑 1:后端只写了 Access-Control-Allow-Origin
header("Access-Control-Allow-Origin: *");
👉 但前端用了:
xhrFields: {
withCredentials: true
}
结果:直接失败
✅ 正确规则:
- 携带 Cookie 时
Allow-Origin不能是*- 必须写成具体域名
❌ 坑 2:OPTIONS 预检请求没处理
浏览器在某些请求前会先发一个:
OPTIONS /api/user
如果后端:
- 没返回 200
- 没返回 CORS 头
👉 正式请求根本不会发
❌ 坑 3:Session 跨域,Cookie 根本没带过去
常见现象:
- AJAX 能请求
- 但登录态丢失
- PHP
$_SESSION永远是空的
原因通常是:
SameSite默认变成Lax- 跨站 Cookie 被浏览器拦截
❌ 坑 4:以为“服务器能访问 = 浏览器也能访问”
这是最致命的误解:
“我用 cURL 请求都成功了,说明接口没问题吧?”
错。
- cURL 成功 ≠ 浏览器允许
- 这是两个完全不同的世界
五、为什么很多人“用 cURL 绕过 AJAX 跨域”?
实际项目中,常见一种做法:
浏览器 AJAX
↓
自己服务器 PHP 接口
↓
PHP cURL 请求第三方接口
👉 这样做的好处:
- 浏览器只请求 同域接口
- 跨域问题转移到 服务器内部
- cURL 无视 CORS,稳定可控
这也是很多:
- 聚合接口
- 中转 API
- 爬虫系统
的标准架构
六、什么时候该用 AJAX?什么时候该用 cURL?
✅ 用 AJAX 的场景
- 前端直接请求自己后端
- 已完全掌控服务端 CORS 配置
- 不依赖第三方 Cookie / Session
✅ 用 PHP cURL 的场景
- 请求第三方 API
- 跨域不可控
- 需要稳定拿数据
- 不希望暴露接口给前端
一句话总结:
能用 cURL 中转的,就别硬刚 AJAX 跨域
七、实战建议(给真正在踩坑的人)
如果你现在遇到的是:
- PHP AJAX 跨域失败
- Session 丢失
- Cookie 不生效
- phpstudy 本地测试 OK,上线就挂
👉 不要乱改代码
先按这个顺序排查:
- 请求是不是浏览器发的?
- 是否需要携带 Cookie?
- CORS 是否返回完整?
- OPTIONS 是否正确响应?
- 能否用 cURL 中转?
AJAX 跨域失败,不是你代码差,是浏览器不让你过。
真正懂原理的人,早就知道什么时候该用 cURL。