必须用 mod_rewrite 在 Apache 核心层拦截防盗链,而非 PHP 判断 Referer;需启用 rewrite_module、设置 AllowOverride All、在资源目录 .htaccess 中配置规则,允许空 Referer 和本域访问,对图片等高带宽资源返回 403。

直接在 XAMPP 中配防盗链,必须用 mod_rewrite 在 Apache 核心层拦截,而不是靠 PHP 里读 $_SERVER['HTTP_REFERER'] —— 后者请求已进 PHP,带宽和解析都花了,纯属“防懒”,不是防盗。
确认 mod_rewrite 已启用且 .htaccess 可生效
XAMPP 默认不加载重写模块,也不允许站点目录下使用 .htaccess。两处必须手动改:
- 打开
C:\xampp\apache\conf\httpd.conf(Windows)或/opt/lampp/etc/httpd.conf(Linux),确保这行未被注释:LoadModule rewrite_module modules/mod_rewrite.so - 找到
<Directory "C:/xampp/htdocs">(或你实际存放资源的路径),把里面的AllowOverride None改成AllowOverride All - 重启 Apache(通过 XAMPP 控制面板),否则所有
.htaccess规则都不起作用
在 .htaccess 中写防盗链规则(只拦静态资源)
规则要放在资源所在目录(如 C:\xampp\htdocs\images\)的 .htaccess 文件里,不是根目录——避免误伤 CSS/JS 等跨域必需资源。
- 只对图片、PDF、ZIP 等高带宽资源设限,别盲目加
js或css,否则本地开发时可能因 Referer 为空或为file://而加载失败 - 允许空 Referer(用户直接输 URL 访问)和本域访问,例如:
RewriteCond %{HTTP_REFERER} !^$和RewriteCond %{HTTP_REFERER} !^https?://(www\.)?localhost(:[0-9]+)?/ [NC] - 用
[F]返回 403 最干净;若想返回占位图,得用[R=302,L]重定向到一张本地图,但注意该图本身不能被规则匹配,否则会死循环
示例(放在 htdocs/images/.htaccess):
XAMPP 8.0.30 是一款免费、开源的跨平台 Web 服务器集成包,专为快速搭建本地 PHP 开发环境而设计。该版本核心组件包括:Apache 2.4.56、MySQL 8.0.33、PHP 8.0.30、phpMyAdmin 5.2.1 等。它支持 Windows、Linux 和 macOS 系统,可让开发者在个人电脑上轻松模拟服务器环境,无需复杂配置即可运行 WordPress、Thin
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?localhost(:[0-9]+)?/ [NC]
RewriteRule \.(jpg|jpeg|png|gif|pdf|zip)$ - [F,NC]本地开发常见问题:Referer 为空或为 file://
浏览器直接双击 HTML 文件打开,或用 VS Code Live Server 启动,Referer 都是空或 file://,会被默认规则拦掉图片。这不是配置错,是本地环境固有行为。
- 解决办法:统一用
http://localhost访问(启动 XAMPP 后访问http://localhost/your-project/index.html),此时 Referer 才是合法 HTTP 协议地址 - 不要在规则里硬写
file://白名单——现代浏览器出于安全限制,根本不会发这个 Referer - 调试时可临时加一行
RewriteCond %{HTTP_REFERER} !^file:// [NC]应急,但上线前务必删掉
为什么不用 PHP 判断 Referer?
因为 XAMPP 本地跑的是真实 Apache + PHP 环境,不是开发服务器模拟器。只要资源路径能被 Apache 直接响应(如 /images/logo.png),请求就根本不会进 PHP。
-
mod_rewrite在 Apache 请求处理早期阶段介入,耗时微秒级,不消耗 PHP 进程 - PHP 方案只能保护
index.php?img=logo.png这类路由转发资源,对直接 URL 访问的静态文件完全无效 - 本地测试时若发现防盗链没生效,第一反应不是规则写错,而是检查
AllowOverride All是否漏改、Apache 是否真重启了
真正难的不是写几行规则,而是理解「防盗链生效的前提是请求走 Apache 静态服务路径」——本地开发时,连这个前提都容易被忽略。

















