Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】

发布时间 - 2025-12-30 00:00:00    点击率:
图片防盗链核心是校验Referer请求头域名是否在白名单内,需通过Laravel中间件拦截/uploads/等路由请求,确保不被Nginx直接响应,并配合CDN或Nginx前置校验提升性能与兼容性。

图片防盗链的核心判断逻辑是检查 Referer 请求头

浏览器在请求图片等静态资源时,通常会带上 Referer 字段,表明来源页面的域名。如果该字段为空、缺失,或域名不在白名单内,就应拒绝响应。Laravel 本身不内置图片防盗链机制,必须通过中间件手动拦截 GET 请求并验证 Referer

用中间件拦截 public 目录下的图片请求(如 /uploads/

关键在于:不能让 Nginx/Apache 直接返回图片文件,否则中间件完全不生效。需确保所有图片请求都经由 Laravel 路由处理。常见做法是把图片路径统一代理到一个控制器方法,或改用 Storage::response() 动态输出。

  • 把图片存放在 storage/app/public/,运行 php artisan storage:link 创建软链接
  • 路由示例:
    Route::get('/uploads/{filename}', [ImageController::class, 'show'])->middleware('check.referer');
  • 不要直接访问 /storage/uploads/xxx.jpg —— 这类路径绕过 Laravel,中间件无效
  • Nginx 配置中需注释或移除对 public/storage 的直接静态文件服务规则(否则防盗链失效)

check.referer 中间件的具体实现要点

该中间件需提取 request()->headers->get('referer'),解析出来源域名,并与白名单比对。注意边界情况:

  • Referer 可能为空(如直接在地址栏输入图片 URL、某些隐私模式、curl 默认不带)—— 应默认拒绝
  • 允许空 Referer 的场景(如微信内置浏览器、部分 PWA)需显式配置开关,不建议默认开启
  • 使用 parse_url($referer, PHP_URL_HOST) 提取 host,避免正则误匹配(如 evil.com.example.com
  • 白名单建议用数组配置在 config/app.php 或环境变量中,例如:IMAGE_REFERER_WHITELIST=['yourapp.com', 'localhost:8000']
  • 匹配时建议转为小写并去除端口(preg_replace('/:\d+$/', '', $host)),避免 YOURAPP.COMlocalhost:8000 被拒
public function handle(Request $request, Closure $next)
{
    $referer = $request->headers->get('referer');
    if (!$referer) {
        abort(403, 'Forbidden: Referer required');
    }
$host = parse_url($referer, PHP_URL_HOST);
if (!$host) {
    abort(403, 'Forbidden: Invalid Referer host');
}

$host = strtolower(preg_replace('/:\d+$/', '', $host));
$whitelist = config('app.image_referer_whitelist', []);

if (!in_array($host, $whitelist)) {
    abort(403, 'Forbidden: Referer not allowed');
}

return $next($request);

}

性能与兼容性注意事项

每次图片请求都走 PHP 和中间件,对高并发场景有压力。生产环境强烈建议结合 CDN 或 Nginx 做前置校验,只将“无法判断”的请求(如带 query 参数的缩略图)交由 Laravel 处理。

  • Nginx 示例(更高效):
    location ~* \.(jpg|jpeg|png|gif)$ {
        valid_referers none blocked yourapp.com *.yourapp.com;
        if ($invalid_referer) {
            return 403;
        }
    }
  • CDN(如 Cloudflare、阿里云 CDN)通常支持 Referer 黑白名单规则,优先启用
  • 移动端 WebView、某些小程序可能不发送 Referer,需配合 token 签名方案(如 /uploads/xxx.jpg?token=sha256(...))作为补充
  • Chrome 85+ 对跨域请求默认使用 strict-origin-when-cross-origin,可能导致 Referer 被截断为 origin,需在白名单中包含完整 origin(含协议和端口)或仅比对 host

实际部署时,Referer 校验只是第一道防线;真正敏感的图片,仍需配合权限控制、临时签名 URL、水印、访问频率限制等组合策略。单靠中间件防不住抓包重放或 Referer 伪造。


# php  # laravel  # apache  # nginx  # 微信  # 浏览器  # app  # 端口  # 小程序  # curl  # 阿里云  # 路由  # 环境变量  # 中间件  # chrome 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤  Laravel怎么实现验证码功能_Laravel集成验证码库防止机器人注册  如何在宝塔面板中创建新站点?  如何利用DOS批处理实现定时关机操作详解  SQL查询语句优化的实用方法总结  Laravel如何优化应用性能?(缓存和优化命令)  ChatGPT回答中断怎么办 引导AI继续输出完整内容的方法  Python高阶函数应用_函数作为参数说明【指导】  如何快速查询网址的建站时间与历史轨迹?  Laravel如何实现全文搜索_Laravel Scout集成Algolia或Meilisearch教程  HTML5建模怎么导出为FBX格式_FBX格式兼容性及导出步骤【指南】  香港网站服务器数量如何影响SEO优化效果?  Laravel Octane如何提升性能_使用Laravel Octane加速你的应用  佛山企业网站制作公司有哪些,沟通100网上服务官网?  详解Huffman编码算法之Java实现  Laravel怎么防止CSRF攻击_Laravel CSRF保护中间件原理与实践  如何在阿里云虚拟服务器快速搭建网站?  Laravel怎么使用Session存储数据_Laravel会话管理与自定义驱动配置【详解】  制作公司内部网站有哪些,内网如何建网站?  如何在企业微信快速生成手机电脑官网?  Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件  php打包exe后无法访问网络共享_共享权限设置方法【教程】  悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  Laravel如何集成Inertia.js与Vue/React?(安装配置)  ai格式如何转html_将AI设计稿转换为HTML页面流程【页面】  网站制作大概要多少钱一个,做一个平台网站大概多少钱?  Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】  php嵌入式断网后怎么恢复_php检测网络重连并恢复硬件控制【操作】  香港服务器选型指南:免备案配置与高效建站方案解析  如何在阿里云购买域名并搭建网站?  如何获取PHP WAP自助建站系统源码?  悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  Gemini手机端怎么发图片_Gemini手机端发图方法【步骤】  Firefox Developer Edition开发者版本入口  企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?  如何在阿里云ECS服务器部署织梦CMS网站?  Java Adapter 适配器模式(类适配器,对象适配器)优缺点对比  如何在云指建站中生成FTP站点?  php中::能调用final静态方法吗_final修饰静态方法调用规则【解答】  宙斯浏览器怎么屏蔽图片浏览 节省手机流量使用设置方法  Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理  浅谈redis在项目中的应用  如何生成腾讯云建站专用兑换码?  html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】  深圳网站制作培训,深圳哪些招聘网站比较好?  如何在自有机房高效搭建专业网站?  微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】  Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层