文件防盗链需web服务器(referer白名单)、php中转下载(隐藏路径+权限校验)与动态授权(token/session绑定)三者协同,禁用public/直链,防止绕过与误伤。

ThinkPHP 文件防盗链不能只靠 PHP 层过滤,必须结合 Web 服务器配置、URL 路由控制和动态访问逻辑三者协同。直接暴露文件路径(如 /uploads/2024/photo.jpg)等于放弃防护主动权。
Web 服务器层设 Referer 白名单(最基础且高效)
这是第一道防线,性能开销低、拦截早。不依赖 PHP 解析,盗链请求在到达应用前就被拒绝。
- Apache:在上传资源所在目录(如
public/uploads/)下放.htaccess,内容如下:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?yourdomain\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|pdf|zip|mp4)$ - [F,NC]
- Nginx:在站点配置的
location块中添加:
valid_referers none blocked server_names *.yourdomain.com;
if ($invalid_referer) { return 403; }
expires 1d;
}
注意:none 允许直接输入 URL 访问,blocked 拦截被代理或篡改 Referer 的请求。
关键资源绝不直出,改用 PHP 中转下载
图片、PDF、Excel 等敏感文件,禁止放在 public/ 下被 URL 直接命中。应存于非 Web 可访问路径(如 runtime/files/),再通过控制器输出。
- 上传时指定安全路径:
'root_path' => runtime_path('files/') - 提供下载接口,例如
/api/file/download?id=abc123 - 控制器中校验权限后调用
readfile(),并设置安全响应头:
header('Content-Disposition: inline; filename="photo.jpg"');
header('Content-Transfer-Encoding: binary');
header('Cache-Control: no-store, no-cache, must-revalidate');
readfile($realPath);
这样既隐藏真实路径,又能插入登录态、IP、时间窗口等校验逻辑。
增强防护:加 Token 或 Session 绑定(防迅雷类工具)
仅靠 Referer 可被伪造,对高价值文件建议启用一次性授权机制。
- 用户点击下载时,生成带时效的 token(如 JWT 或加密字符串),存入 session 或缓存
- 下载接口验证 token 是否有效、未过期、且与当前用户绑定
- 避免把文件 ID 或路径拼在 GET 参数里,改用 POST 提交或从 session 读取
示例逻辑:if (!session('download_token') || !verify_token($_GET['t'])) { abort(403); }
补充细节:防止绕过与误伤
防盗链规则容易和 ThinkPHP 的 URL 重写冲突,导致正常页面 404。务必注意:
- 将防盗链规则放在路由重写规则之前(Nginx 中 location 顺序很重要)
- 排除 PHP 脚本和 API 接口路径,例如 Nginx 中加:
location ~ \.php$ { ... }单独处理,不参与防盗链匹配 - 测试空 Referer 场景(如微信内置浏览器、某些 App)是否被误拦,必要时放宽
none条件
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











