本文目录导读:

在PHP项目中配置防盗链,主要目的是防止其他网站直接引用你的图片、CSS、JS等静态资源,从而节省带宽和服务器资源。
通常有两种主流方式:服务器层面(推荐,最有效) 和 PHP代码层面。
服务器层面配置(最高效、最推荐)
这种方式在资源被发送给用户之前就被拦截了,性能开销最小。
Nginx 配置防盗链
Nginx 通过 valid_referers 指令实现,在对应的 server 块或 location 块中添加:
server {
listen 80;
server_name yourdomain.com;
# 对图片、CSS、JS等静态资源进行防盗链
location ~* \.(gif|jpg|jpeg|png|webp|bmp|ico|svg|css|js|woff|ttf|mp4|zip|rar)$ {
# 允许的来源域名列表(务必包含你自己的域名)
valid_referers none blocked server_names
*.yourdomain.com # 允许所有子域名
yourdomain.com
*.trusted-partner.com; # 允许合作伙伴域名
if ($invalid_referer) {
# 如果来源不在白名单中,返回 403 或重定向到指定图片
return 403;
# 或者重定向到你设置的防盗链图片(注意:这个图片不能在防盗链范围内)
# rewrite ^/.*$ /path/to/deny.jpg break;
}
}
# 或者更简单的写法(推荐,逻辑更清晰)
location /uploads/ {
valid_referers none blocked server_names *.yourdomain.com yourdomain.com;
if ($invalid_referer) {
return 403;
}
}
}
配置解释:
none:允许直接通过浏览器地址栏访问(Referer 为空)。blocked:允许 Referer 被隐藏的请求(如某些防火墙)。server_names:允许来自本服务器配置的所有域名。$invalid_referer:如果来源不匹配,则为 true。
生效后需重启/重载 Nginx:
nginx -s reload
Apache 配置防盗链
Apache 使用 mod_rewrite 模块,在 .htaccess 文件或虚拟主机配置中添加:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?yourdomain.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?yourpartner.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|bmp|webp|css|js)$ - [F,NC,L]
# 或者返回一张指定的防盗链图(该图片不能在规则范围内)
# RewriteRule \.(jpg|jpeg|png|gif)$ /path/to/deny.jpg [R,L]
注意:需要确保 Apache 开启了 mod_rewrite 且目录允许覆盖(AllowOverride All)。
PHP 代码层面配置(适合无法控制服务器的场景)
如果你的项目托管在虚拟主机或无法修改服务器配置(如 SAE、BAE),可以在 PHP 入口文件(如 index.php)或具体下载文件的 PHP 脚本中处理。
代码示例:通过读取 HTTP_REFERER 头判断
<?php
// 放在需要防盗链的图片/文件处理脚本的最开头,或者全局入口文件
function checkReferer() {
// 允许的域名列表(务必包含你自己的所有域名,不含 http://)
$allowed_domains = [
'yourdomain.com',
'www.yourdomain.com',
'cdn.yourdomain.com',
'localhost', // 本地测试
];
// 获取来源 Referer
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
// 情况1:没有来源(直接访问,例如手机端或命令行直接下载)
// 如果要求必须携带来源才能访问,可以返回 false,但会导致直接访问被拒
// 如果需要允许直接访问,解除下面这行的注释(配合图片防盗链通常建议允许直接访问)
// if (empty($referer)) return true;
$allowed = false;
if (!empty($referer)) {
// 解析 Referer 的域名部分(只保留主机名)
$referer_host = parse_url($referer, PHP_URL_HOST);
foreach ($allowed_domains as $domain) {
// 检查是否完全匹配或属于子域名
if ($referer_host === $domain ||
stripos($referer_host, '.' . $domain) !== false) {
$allowed = true;
break;
}
}
} else {
// Referer 为空:根据业务需要决定
// 某些爬虫或软件不发送 Referer,通常建议返回 true 允许直接访问
$allowed = true;
}
if (!$allowed) {
// 阻止访问:显示 403 或跳转到一张警告图片
header('HTTP/1.1 403 Forbidden');
// 可选:返回一张指定的防盗链图片(这张图片必须可以被直接访问)
// header('Location: http://yourdomain.com/deny.jpg');
// 或者直接输出一段文字
die('Access Denied: Hotlinking is not allowed.');
}
}
// 在文件下载脚本或图片展示页面调用
checkReferer();
// --- 以下代码是你的正常业务逻辑 ---
//
// $file = $_GET['file'];
// readfile($file);
注意事项(重要)
- HTTP_REFERER 不可伪造?:实际上很容易伪造,所以代码层面防君子不防小人,对于重要的资源(如图片、视频),务必使用服务器层面的配置。
- 对 CDN 的影响:如果使用了 CDN(如 Cloudflare、阿里云 CDN),需要在 CDN 层面配置防盗链,而不是仅仅在源站配置,否则 CDN 缓存会绕过 Referer 检查。
- 空 Referer 的处理:浏览器地址栏直接输入、微信/QQ 内置浏览器、某些下载工具(wget/curl 不加 --referer)会发送空 Referer,如果允许这些情况访问,代码里要给
$allowed = true,否则用户无法直接打开你的图片。 - 性能考虑:如果是高频访问的静态资源(如首页图片),在 PHP 里判断 Referer 会导致服务器产生大量不必要的 PHP 进程开销(即使没在读取图片前就拦截了,PHP 解释器也需要先跑起来)。强烈建议优先使用服务器层面配置。
总结建议
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 自己有服务器权限 | Nginx/Apache 配置 | 零开销,直接由 Web 服务器拦截,不影响 PHP 性能 |
| 虚拟主机或 PHP 环境 | PHP 代码 + Web服务器配置 | 先用 PHP 做基础拦截,如果支持 .htaccess 就加上 |
| 使用 CDN | CDN 防盗链设置 | 在 CDN 边缘节点拦截,比源站拦截更省流量 |
| 仅防百度/谷歌等爬虫 | robots.txt + User-Agent 过滤 | 不需要判断 Referer,robots.txt 可以禁止爬虫直接爬取资源 |
最后的忠告:防盗链的 HTTP_REFERER 极易被伪造,如果你需要非常强的资源保护(如付费视频、原创高清图),请考虑以下方案:
- 加时间戳签名(Nginx 的 secure_link 模块 或 自己写签名逻辑)。
- 使用 OSS/CDN 的 Referer 黑白名单 + 空 Referer 拦截。
- 验证码或登录鉴权(最严格,但用户体验稍差)。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播