
本文介绍如何通过编写轻量级 php 代理脚本绕过浏览器 cors 限制,安全地转发前端 ajax 请求至第三方 api(如 expensify),并提供可直接运行的代码、关键修复点及安全注意事项。
本文介绍如何通过编写轻量级 php 代理脚本绕过浏览器 cors 限制,安全地转发前端 ajax 请求至第三方 api(如 expensify),并提供可直接运行的代码、关键修复点及安全注意事项。
在前端开发中,当 JavaScript 直接向跨域 API(如 https://www.expensify.com/api)发起请求时,浏览器会因同源策略(Same-Origin Policy)阻止响应,抛出 CORS 错误。虽然设置 Access-Control-Allow-Origin: * 可解决部分问题,但真正的 CORS 控制权在目标服务器端——你无法强制第三方 API 开放跨域权限。此时,最可靠、标准的解决方案是:在自有服务器上部署一个 PHP 代理脚本,由前端请求该代理,再由 PHP 后端以服务端身份调用目标 API。
以下是经过优化、修复并增强安全性的 PHP 代理实现(保存为 proxy.php):
<?php // proxy.php —— 安全、健壮的 CORS 代理脚本
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, X-Requested-With, Authorization');
header('Access-Control-Max-Age: 3600');
// 处理预检请求(OPTIONS)
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit;
}
// ✅ 关键修复1:严格校验并过滤目标 URL,防止 SSRF 和开放重定向
$allowedHosts = ['www.expensify.com', 'api.example.com']; // 替换为你实际需要调用的域名
$targetUrl = filter_input(INPUT_POST, 'url', FILTER_SANITIZE_URL);
if (!$targetUrl || !filter_var($targetUrl, FILTER_VALIDATE_URL)) {
http_response_code(400);
echo json_encode(['error' => 'Invalid or missing URL parameter']);
exit;
}
$parsed = parse_url($targetUrl);
if (!$parsed || !in_array($parsed['host'], $allowedHosts)) {
http_response_code(403);
echo json_encode(['error' => 'Target host not allowed']);
exit;
}
// ✅ 关键修复2:统一处理 GET/POST,支持 query string + POST body 混合传递
$method = strtoupper($_SERVER['REQUEST_METHOD']);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $targetUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 生产环境建议设为 true 并配置 CA 证书
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// POST 请求:发送 $_POST 数据(自动编码为 application/x-www-form-urlencoded)
if ($method === 'POST' && !empty($_POST)) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($_POST));
} elseif ($method === 'GET' && !empty($_GET)) {
// GET 请求:确保 URL 已含参数,不重复拼接
$targetUrl .= (parse_url($targetUrl, PHP_URL_QUERY) ? '&' : '?') . http_build_query($_GET);
curl_setopt($ch, CURLOPT_URL, $targetUrl);
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
// ✅ 关键修复3:正确透传响应状态码与原始内容类型(非仅 JSON)
if ($error) {
http_response_code(502);
header('Content-Type: application/json');
echo json_encode(['error' => 'Curl request failed', 'details' => $error]);
} else {
// 建议:根据实际 API 响应头动态设置 Content-Type(此处简化为 JSON)
header('Content-Type: application/json; charset=utf-8');
http_response_code($httpCode);
echo $response; // 直接输出原始响应体,保持 API 兼容性
}
前端调用方式(关键修改)
将原 JS 中的 url 指向你的 proxy.php,并必须将原始 API 地址作为 url 参数传入:
$("#login").click(function () {
var partnerUserID = $("#email").val();
var partnerUserSecret = $("#password").val();
$.ajax({
type: "POST",
url: "proxy.php", // ✅ 指向本地代理文件
data: {
url: "https://www.expensify.com/api?command=Authenticate", // ✅ 必须传递目标 URL
partnerName: "", // 根据实际需求填写
partnerPassword: "",
partnerUserID: partnerUserID,
partnerUserSecret: partnerUserSecret
},
cache: false,
success: function (data) {
// data 即为 Expensify API 的原始 JSON 响应
const response = typeof data === 'string' ? JSON.parse(data) : data;
if (response.jsonCode === 200) {
sessionStorage.setItem('authToken', response.authToken);
window.location.href = "dashboard.html";
} else {
alert(getErrorMessage(response.jsonCode));
}
},
error: function (xhr) {
console.error("Proxy request failed:", xhr.status, xhr.responseText);
alert("Login failed. Please check your connection.");
}
});
});
⚠️ 重要安全提醒(生产环境必读)
-
禁止开放任意 URL:原始代码中
$_REQUEST['url']极易导致 SSRF(服务器端请求伪造)或开放重定向攻击。务必如示例所示,白名单校验目标主机。 -
禁用
CURLOPT_SSL_VERIFYPEER => false:开发调试可临时关闭,上线前必须启用 SSL 证书验证,并配置正确的 CA bundle。 - 添加身份认证与速率限制:公开代理可能被滥用,建议对接口增加 token 验证或 IP 限流(如使用 Redis)。
-
避免敏感信息泄露:不要在代理日志中记录
$_POST数据(尤其密码、token)。 -
考虑使用更成熟的方案:长期项目推荐 Nginx 反向代理(
proxy_pass)或专用网关(如 Kong),PHP 代理仅适用于快速验证或轻量场景。
此代理脚本已通过核心逻辑重构,兼顾功能性、安全性与可维护性,可立即集成到现有项目中。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











