必须将http接口升级为https或通过https反向代理访问,因为现代浏览器会直接拦截https页面中的http请求,且该拦截发生在协议层,无法通过cors配置、前端模式调整或后端代请求绕过。

HTTPS页面调用HTTP接口直接被浏览器拦截
现代浏览器(Chrome、Firefox、Edge)默认阻止 HTTPS 页面加载 HTTP 资源,这属于主动混合内容(active mixed content)策略。哪怕只是 fetch('http://api.example.com/data'),控制台立刻报错:Mixed Content: The page at 'https://site.com/' was loaded over HTTPS, but requested an insecure resource 'http://api.example.com/data'. 浏览器连请求都不会发出去,PHP 后端根本收不到——这不是 CORS 问题,是协议层拦截。
- 不能靠改 PHP 的
header('Access-Control-Allow-Origin: *')解决,因为请求压根没发出 - 不能靠前端加
mode: 'no-cors'绕过,它只支持简单请求且无法读响应体 - 本地开发用
http://localhost测试时看似正常,一上生产 HTTPS 环境就崩,容易误判
必须让接口走 HTTPS,没有例外
唯一合规解法是把 HTTP 接口升级为 HTTPS。不是“建议”,是强制要求。PHP 本身不决定协议,关键看接口部署环境:
- 如果接口在你自己的服务器上:给 Nginx/Apache 配 SSL 证书(Let’s Encrypt 免费),把
http://api.yoursite.com改成https://api.yoursite.com - 如果是第三方 HTTP 接口(如老旧内网服务):必须加一层反向代理,比如用 Nginx 把
https://your.com/proxy/old-api转发到http://192.168.1.100:8080,前端只跟 HTTPS 地址通信 - 切勿在 PHP 中用
file_get_contents('http://...')代为请求再返回给前端——这会暴露后端 IP、拖慢响应、绕过前端鉴权逻辑
反向代理配置示例(Nginx)
这是最常踩坑的环节:代理要透传关键头、处理重定向、避免缓存脏数据。以下是最小安全配置片段:
location /proxy/old-api {
proxy_pass http://192.168.1.100:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_buffering off;
}
-
proxy_pass末尾的/很关键,漏掉会导致路径拼接错误(如/proxy/old-api/user变成http://.../old-api/user) - 必须设置
X-Forwarded-Proto,否则 PHP 的$_SERVER['HTTPS']会误判,影响 Laravel 等框架的 URL 生成 - 不要加
add_header Access-Control-Allow-Origin "*"到代理块里——CORS 应由后端接口自己控制,代理层不该越权
PHP 后端也要检查 Referer 和协议一致性
即使前端解决了 HTTPS 调用,PHP 接口仍可能因协议校验失败而拒绝请求。常见于手动验证来源的场景:
立即学习“PHP免费学习笔记(深入)”;
- 别用
$_SERVER['HTTP_REFERER']做权限判断——它可被伪造,且 HTTPS 页面发起的请求中该字段值仍是https://...,与 HTTP 接口不匹配 - 如果必须校验来源协议,应检查
$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'(前提是代理已传这个头) - 生成跳转链接或资源 URL 时,用
$_SERVER['REQUEST_SCHEME']或parse_url($_SERVER['REQUEST_URI'], PHP_URL_SCHEME),而非硬写http://
混合协议的本质是信任链断裂。浏览器拦 HTTP 不是因为讨厌它,而是怕中间人篡改响应。所有“绕过”方案(禁用浏览器安全策略、降级页面为 HTTP)都等于主动拆掉防护墙。真正的解决点永远在接口端——要么它上 HTTPS,要么你用可信代理兜住它。











