空色天絵 / NEO TOKYO NOIR 01
917 字
5 分钟
PHP 实现 HTTPS 图片反向代理 (解决防盗链与跨域)
在前端开发中,我们经常遇到引用的第三方图片无法显示,通常是因为目标服务器开启了防盗链(Hotlink Protection),或者因为协议不同(HTTPS 网站加载 HTTP 图片)导致浏览器拦截。
本文提供一个轻量级的 PHP 解决方案,通过服务器端反向代理来中转图片请求。
1. 核心代码 (proxy.php)
将以下代码保存为 proxy.php 文件,放置在你的网站根目录或工具目录下。
<?php/** * Simple PHP Image Proxy * 用于中转 HTTPS 图片请求 */
// 1. 获取参数if (isset($_GET['url'])) { $url = $_GET['url'];
// 2. 安全校验:验证是否为合法的 HTTPS 图片链接 // 限制只能访问 HTTPS,且后缀必须为常见的图片格式 if (filter_var($url, FILTER_VALIDATE_URL) && strpos($url, 'https://') === 0 && preg_match('/\.(jpeg|jpg|png|gif|webp)$/i', $url)) {
// 3. 初始化 cURL $ch = curl_init();
// 4. 设置 cURL 选项 curl_setopt($ch, CURLOPT_URL, $url); // 设置目标 URL curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);// 将结果作为字符串返回而不是直接输出 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);// 忽略 SSL 证书验证 (解决部分自签名证书问题) curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);// 跟随重定向
// 伪造 User-Agent (可选,防止对方服务器拦截爬虫) curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
// 5. 执行请求 $imageData = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
// 6. 处理响应 if ($httpCode == 200 && $imageData) { // 动态获取图片 MIME 类型 (比单纯看后缀更准确) $finfo = new finfo(FILEINFO_MIME_TYPE); $mimeType = $finfo->buffer($imageData);
// 设置响应头并输出图片数据 header('Content-Type: ' . $mimeType); // 可以添加缓存头,减少服务器压力 header('Cache-Control: public, max-age=86400'); echo $imageData; } else { // 请求失败 http_response_code(404); echo "Image not found or access denied."; } } else { // URL 格式不合法 http_response_code(400); echo "Invalid image URL."; }} else { echo "No image URL provided.";}?>2. 代码原理解析
- 参数获取 (
$_GET): 脚本接收一个url参数,即你想要代理的原始图片地址。 - 安全过滤 (
filter_var&preg_match):
- 检查这是否是一个合法的 URL。
- 强制要求
https://开头(安全性考虑)。 - 限制文件后缀(jpg, png 等),防止被恶意用户用来请求服务器上的敏感文件(如
.php或.config)。
- cURL 请求: PHP 服务器作为“中间人”,向目标服务器发起请求下载图片数据。
CURLOPT_SSL_VERIFYPEER: 设置为false可以容忍目标服务器 SSL 证书过期或配置错误的情况。
- MIME 类型检测 (
finfo): 不依赖文件后缀,而是通过文件内容二进制数据判断真实的图片类型(如image/jpeg),确保浏览器能正确解析。 - 输出流: 设置好
Content-Type头信息后,直接将二进制图片数据“打印”给浏览器。
3. 如何使用
假设你的 PHP 文件部署在 https://yourserver.com/proxy.php。
调用方式
在 HTML <img> 标签中,将 src 指向你的代理文件,并将目标图片作为参数传递:
<img src="[https://yourserver.com/proxy.php?url=https://example.com/protected-image.jpg](https://yourserver.com/proxy.php?url=https://example.com/protected-image.jpg)">4. ⚠️ 安全与性能警告
虽然这段代码很方便,但在生产环境使用时,请务必注意以下几点:
WARNINGSSRF (服务端请求伪造) 风险 不要去掉
strpos($url, 'https://')的检查,也不要随意放宽域名限制。如果攻击者传入http://localhost:3306或内网 IP,可能会导致你的服务器内网信息泄露。
NOTE性能优化建议 每次请求都通过 PHP 转发会消耗服务器流量和 CPU。如果流量较大,建议:
- 开启 CDN:给你的
proxy.php所在的域名套上 Cloudflare 等 CDN。- 本地缓存:在 PHP 中将获取到的图片保存到本地
/cache/目录,下次请求时直接读取本地文件,不再请求远程服务器。
PHP 实现 HTTPS 图片反向代理 (解决防盗链与跨域)
https://blog.obve.cn/posts/91528/
鲁公网安备37048102006944号