防盗链必须用 mod_rewrite 而非仅靠 Referer 判断,因为 mod_rewrite 在请求进入 PHP 前拦截,避免带宽和解析开销;PHP 中检查 Referer 已晚,仅属“防懒”。

防盗链为什么必须用 mod_rewrite 而不是仅靠 Referer 判断
因为 Apache 的 mod_rewrite 是唯一能在请求进入 PHP 之前就拦截并重定向盗链请求的模块。单纯在 PHP 里用 $_SERVER['HTTP_REFERER'] 检查,请求已经消耗了带宽、触发了 PHP 解析,起不到“防盗”作用——只算“防懒”。mod_rewrite 规则运行在 Apache 核心层,响应快、开销低,且能直接返回 403 或跳转到占位图。
在 XAMPP 的 httpd.conf 中启用并配置 rewrite 规则
XAMPP 默认禁用 mod_rewrite,且默认不加载用户级 .htaccess 支持。需手动确认两处:
- 打开
C:\xampp\apache\conf\httpd.conf(或对应安装路径),确保这行未被注释:LoadModule rewrite_module modules/mod_rewrite.so - 找到
<directory></directory>块(或你实际存放站点的目录),把里面的AllowOverride None改为AllowOverride All,否则 .htaccess 中的 rewrite 规则不会生效 - 重启 Apache(通过 XAMPP 控制面板)
改完后,可在 C:\xampp\htdocs\.htaccess 中写规则,例如限制图片盗链:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?yourdomain\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ - [F]注意:[F] 返回 403;若想返回一张占位图,把最后一行换成:RewriteRule \.(jpg|jpeg|png|gif|webp)$ /images/forbidden.png [R,L](需确保该路径存在且可访问)
Referer 空值和浏览器隐私策略导致的误拦
现代浏览器(尤其启用了 Referrer-Policy: strict-origin-when-cross-origin 或使用 HTTPS→HTTP 跳转时)会清空 Referer。此时 %{HTTP_REFERER} 为空,你的规则若没加 !^$ 判断,就会把合法的直接访问也拒掉。
- 务必保留
RewriteCond %{HTTP_REFERER} !^$这一行,允许空 referer 访问(比如用户从书签、微信内嵌浏览器、某些 PWA 场景) - 不要只写域名白名单,加上协议和子域通配:
!^https?://(www\.)?yourdomain\.com,否则https://yourdomain.com和http://www.yourdomain.com都可能被误拦 - 测试时用 curl 模拟不同 referer:
curl -H "Referer: https://evil-site.com" http://localhost/test.jpg,比浏览器 F5 更可靠
Windows 路径大小写与 XAMPP 的 RewriteBase 陷阱
XAMPP 在 Windows 上运行,但 mod_rewrite 默认区分大小写(jpg ≠ JPG)。如果网站里混用大小写后缀,规则会漏掉部分请求。
- 在
.htaccess开头加RewriteEngine On后,立即加一行:Options +FollowSymLinks(XAMPP 默认关闭此选项,否则 rewrite 可能静默失效) - 如果项目不在根目录(比如放在
http://localhost/myapp/),必须加RewriteBase /myapp/,否则重写路径会相对于物理路径而非 URL 路径,导致 404 - 避免用
.*匹配文件名,改用具体扩展名列表,减少正则开销;如需支持更多格式,追加即可:\.(jpg|jpeg|png|gif|webp|svg|ico)$
规则生效后,Apache 错误日志(C:\xampp\apache\logs\error.log)里出现 client denied by server configuration 表示拦截成功;若无日志且未生效,优先检查 AllowOverride 是否真改对了目录块,这是 XAMPP 用户最常卡住的地方。

















