前端实现图片防盗链技术详解 - 原理分析与SpringBoot解决方案

前端实现图片防盗链技术详解 - 原理分析与SpringBoot解决方案
在这里插入图片描述
🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
🎐 个人CSND主页——Micro麦可乐的博客
🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战
🌺《RabbitMQ》专栏19年编写主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战
🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解
🌛《开源项目》本专栏主要介绍目前热门的开源项目,带大家快速了解并轻松上手使用
🍎《前端技术》专栏以实战为主介绍日常开发中前端应用的一些功能以及技巧,均附有完整的代码示例
✨《开发技巧》本专栏包含了各种系统的设计原理以及注意事项,并分享一些日常开发的功能小技巧
💕《Jenkins实战》专栏主要介绍Jenkins+Docker的实战教程,让你快速掌握项目CI/CD,是2024年最新的实战教程
🌞《Spring Boot》专栏主要介绍我们日常工作项目中经常应用到的功能以及技巧,代码样例完整
👍《Spring Security》专栏中我们将逐步深入Spring Security的各个技术细节,带你从入门到精通,全面掌握这一安全技术
如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~

前端实现图片防盗链技术详解 - 原理分析与SpringBoot解决方案

1. 前言:图片盗链的危害与影响

在现代 Web 应用中,网站往往需要展示大量图片资源(商品图、文章配图、用户头像等)。若不做防护,其他站点或爬虫可以直接引用这些图片 URL,占用带宽、盗用版权、造成服务器压力过大会导致:

  • 流量损失:盗链消耗您的服务器带宽
  • 成本增加:CDN和服务器费用飙升
  • 版权侵犯:原创内容被非法使用
  • SEO影响:搜索引擎排名下降

为此,我们需要为图片资源加一道“防盗链”保护,确保只有合法来源或携带正确凭证的请求才能成功获取图片。本文博主将带着小伙伴们深入解析防盗链技术原理,并提供前后端完整解决方案。


2. 为什么要实施防盗链?

我们先来看一个例子:假设你的云服务器按带宽、流量计费,并且开通了CDN加速服务,那么图片被盗链你可能面临下图问题

在这里插入图片描述


所以实施防盗链,可以解决以下几个问题:

节省带宽与流量成本
非法盗链会导致大量免费流量被外站消耗,增加服务器的网络和流量费用。

保护版权与资源安全
防止未授权站点随意引用和传播图片资源,保障内容提供方的利益。

防止爬虫恶意抓取
结合签名或 Referer 校验,可以有效拦截简单爬虫,避免批量抓取。

提升访问性能
当检测到非授权请求时,直接返回 403 或空白图,减轻后端压力。


3. 防盗链核心技术原理

主要有两种常见思路:

Referer 校验
后端检查 HTTP 请求头中的 Referer,只有来自本站页面的请求才允许访问。

签名(Token)校验
前端在图片 URL 上附加时间戳与签名(HMAC/MD5),后端校验签名并判断是否过期。

Referer 校验简单易用,但可以被伪造;签名方案更安全,可以自定义过期时间、权限范围。

3.1 Referer 校验

当浏览器请求资源时,会在Header中包含来源页面地址:

GET /image.jpg HTTP/1.1 Host: your-domain.com Referer: https://attacker-site.com/stolen-page.html 

防盗链核心逻辑:

在这里插入图片描述


后端校验Referer:

@ConfigurationpublicclassSecurityConfigimplementsWebMvcConfigurer{//配置在yml文件中的合法域名@Value("${allowed.domains}")privateList<String> allowedDomains;@OverridepublicvoidaddInterceptors(InterceptorRegistry registry){ registry.addInterceptor(newRefererInterceptor(allowedDomains)).addPathPatterns("/images/**");}}publicclassRefererInterceptorimplementsHandlerInterceptor{privatefinalSet<String> allowedDomains;publicRefererInterceptor(List<String> domains){this.allowedDomains =newHashSet<>(domains);}@OverridepublicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{String referer = request.getHeader("Referer");if(referer ==null){// 允许无Referer的直接访问(如浏览器地址栏)returntrue;}try{String domain =newURL(referer).getHost();if(allowedDomains.contains(domain)){returntrue;}}catch(MalformedURLException e){// URL格式错误视为非法}// 返回防盗链提示图 response.setContentType("image/png");Files.copy(Paths.get("static/anti-leech.png"), response.getOutputStream());returnfalse;}}

3.2 签名(Token)校验

3.2.1 前端实现思路
  • 计算签名:用约定好的 secretKey 对图片路径(或文件名)+ 时间戳做 HMAC/MD5 计算。
  • 拼接 URL:/images/{filename}?ts={timestamp}&sign={signature}
  • 将带签名的 URL 输出到页面或组件内
<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>防盗链示例</title></head><body><h3>商品展示图:</h3><imgid="productImg"alt="Product"><script>// 约定的密钥(不能泄露到公网,示例仅展示逻辑)constSECRET_KEY='MySuperSecretKey';// 简单 MD5 签名(生产环境请使用 HMAC)// 这里只借助外部库 md5.min.jsfunctiongenerateSignedUrl(filename){const ts = Date.now();// 签名内容:filename + ts + SECRET_KEYconst raw =`${filename}${ts}${SECRET_KEY}`;const sign =md5(raw);return`/images/${filename}?ts=${ts}&sign=${sign}`;}// 使用示例 document.getElementById('productImg').src =generateSignedUrl('sample.jpg');</script><!-- 引入 md5 库 --><scriptsrc="https://cdn.jsdelivr.net/npm/blueimp-md5/js/md5.min.js"></script></body></html>
3.2.1 后端(Spring Boot)示例

添加依赖
Spring Boot 项目中追加 commons-codec 依赖

<!-- pom.xml --><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.15</version></dependency>

编写签名校验拦截器

importorg.apache.commons.codec.digest.DigestUtils;importorg.springframework.stereotype.Component;importorg.springframework.web.servlet.HandlerInterceptor;importjakarta.servlet.http.HttpServletRequest;importjakarta.servlet.http.HttpServletResponse;importjava.io.File;importjava.io.IOException;@ComponentpublicclassImageAuthInterceptorimplementsHandlerInterceptor{privatestaticfinalStringSECRET_KEY="MySuperSecretKey";// 签名有效期:5 分钟privatestaticfinallongEXPIRE_MILLIS=5*60*1000;@OverridepublicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsIOException{String tsParam = request.getParameter("ts");String signParam = request.getParameter("sign");String uri = request.getRequestURI();// e.g. /images/sample.jpgif(tsParam ==null|| signParam ==null){ response.sendError(HttpServletResponse.SC_FORBIDDEN);returnfalse;}long ts =Long.parseLong(tsParam);long now =System.currentTimeMillis();if(now - ts >EXPIRE_MILLIS){// 超时 response.sendError(HttpServletResponse.SC_FORBIDDEN,"链接过期");returnfalse;}// 计算服务器端签名String path = uri.substring("/images/".length());// sample.jpgString raw = path + tsParam +SECRET_KEY;String serverSign =DigestUtils.md5Hex(raw);if(!serverSign.equalsIgnoreCase(signParam)){ response.sendError(HttpServletResponse.SC_FORBIDDEN);returnfalse;}// 签名校验通过,继续处理请求(交给静态文件 handler)returntrue;}}

注册拦截器

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.*;@ConfigurationpublicclassWebConfigimplementsWebMvcConfigurer{@AutowiredprivateImageAuthInterceptor imageAuthInterceptor;@OverridepublicvoidaddInterceptors(InterceptorRegistry registry){ registry.addInterceptor(imageAuthInterceptor).addPathPatterns("/images/**");}@OverridepublicvoidaddResourceHandlers(ResourceHandlerRegistry registry){// 将 /images/** 映射到本地文件系统目录 registry.addResourceHandler("/images/**").addResourceLocations("file:/opt/app/images/");}}

存放图片
将需要防盗链的图片放到服务器 /opt/app/images/ 目录下,例如 sample.jpg


4. 高级防护策略

通过上述的代码演示,无论你是使用 Referer 校验,还是基于签名校验,相信小伙伴已经可以轻松应用于自己的项目中,这里博主再简单罗列两点高级防护策略,供小伙伴们参考

4.1 动态水印技术

将图片资源默认都加上动态水印

publicvoidaddWatermark(InputStream imageStream,OutputStream output,String text)throwsIOException{BufferedImage image =ImageIO.read(imageStream);Graphics2D g = image.createGraphics();// 设置水印透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.3f)); g.setColor(Color.BLACK); g.setFont(newFont("Arial",Font.BOLD,30));// 计算水印位置FontMetrics metrics = g.getFontMetrics();int x =(image.getWidth()- metrics.stringWidth(text))/2;int y = image.getHeight()-50;// 添加文字水印 g.drawString(text, x, y); g.dispose();ImageIO.write(image,"jpg", output);}

4.2 智能行为分析

我们还可以设置一些行为限制,比如 几秒内可以访问多少次

@ComponentpublicclassImageRequestAnalyzer{privatefinalMap<String,RequestCounter> ipCounters =newConcurrentHashMap<>();@Scheduled(fixedRate =60000)// 每分钟清理publicvoidcleanCounters(){ ipCounters.entrySet().removeIf(entry -> entry.getValue().isExpired());}publicbooleanisSuspiciousRequest(HttpServletRequest request){String ip = request.getRemoteAddr();String path = request.getRequestURI();RequestCounter counter = ipCounters.computeIfAbsent( ip + path, k ->newRequestCounter()); counter.increment();// 规则1: 10秒内超过20次请求if(counter.getCount(10)>20)returntrue;// 规则2: 1分钟内超过100次请求if(counter.getCount(60)>100)returntrue;// 规则3: 异常User-AgentString ua = request.getHeader("User-Agent");if(ua ==null|| ua.contains("Python")|| ua.contains("curl")){returntrue;}returnfalse;}staticclassRequestCounter{privatefinalList<Long> timestamps =newArrayList<>();publicsynchronizedvoidincrement(){ timestamps.add(System.currentTimeMillis());}publicsynchronizedintgetCount(int seconds){long cutoff =System.currentTimeMillis()- seconds *1000L; timestamps.removeIf(t -> t < cutoff);return timestamps.size();}publicbooleanisExpired(){return timestamps.isEmpty()||System.currentTimeMillis()- timestamps.get(0)>3600000;}}}

5. 结语

本文博主讲解了 Referer校验 + 签名校验两种防盗链方案,其中签名校验 我们实现在前端生成带有防盗链签名的图片 URL,后端(Spring Boot)在拦截器中校验签名并检查有效期,只有合法请求才能获取图片资源。该方案优点在于:

  • 安全性高:签名不可伪造,且可设置过期
  • 灵活可扩展:可加入用户鉴权、权限控制等
  • 轻量无侵入:仅依赖拦截器和静态资源映射

希望本文能帮助你快速上手图片防盗链实现,保护自己的图片资源不被非法盗链。如果你在实践过程中有任何疑问或更好的扩展思路,欢迎在评论区留言,最后希望大家一键三连给博主一点点鼓励!


前端技术专栏回顾:

01【前端技术】 ES6 介绍及常用语法说明
02【前端技术】标签页通讯localStorage、BroadcastChannel、SharedWorker的技术详解
03 前端请求乱序问题分析与AbortController、async/await、Promise.all等解决方案
04 前端开发中深拷贝的循环引用问题:从问题复现到完美解决
05 前端AJAX请求上传下载进度监控指南详解与完整代码示例
06 TypeScript 进阶指南 - 使用泛型与keyof约束参数
07 前端实现视频文件动画帧图片提取全攻略 - 附完整代码样例
08 前端函数防抖(Debounce)完整讲解 - 从原理、应用到完整实现
09 JavaScript异步编程 Async/Await 使用详解:从原理到最佳实践
10 前端图片裁剪上传全流程详解:从预览到上传的完整流程
11 前端大文件分片上传详解 - Spring Boot 后端接口实现

Read more

机器人多轴协同控制实战指南(基于ROS和EtherCAT的实现方案)

第一章:机器人多轴协同控制概述 在现代工业自动化系统中,机器人多轴协同控制是实现高精度运动与复杂轨迹执行的核心技术。该技术通过协调多个伺服轴的实时运动,确保机械臂或移动平台能够在三维空间中完成精确操作,广泛应用于装配、焊接、喷涂和搬运等场景。 协同控制的基本原理 多轴协同依赖于统一的运动规划算法与实时通信机制。控制器根据目标路径生成各轴的位置、速度和加速度指令,并通过总线协议(如EtherCAT、CANopen)同步下发至驱动器。为保证运动平滑性,通常采用插补算法进行轨迹规划。 典型控制架构 * 上位机负责路径规划与任务调度 * 运动控制器执行插补计算与指令分发 * 伺服驱动器接收指令并闭环控制电机 * 反馈单元(如编码器)提供位置检测信号 常用插补方式对比 插补类型适用场景精度计算复杂度直线插补简单轨迹移动中低圆弧插补曲线轮廓加工高中样条插补高速平滑路径极高高 代码示例:三轴直线插补逻辑 /* 实现XYZ三轴直线插补 */ void linear_interpolation(float x, float y, float z, float feed_

最大无本体具身数据集开源!简智机器人联合百度百舸,加速具身智能应用落地

1.    简智机器人开源行业最大规模的无本体具身数据集 1 月 5 日,简智新创(北京)机器人科技有限公司(以下简称「简智机器人」)正式开源「RealOmni-Open DataSet」无本体具身数据集,数据集总计包含超过 10,000 小时、百万条以上的真实操作记录,是目前行业已知数据规模最大且每一项技能数据量最多的无本体开源数据集。 当前,简智机器人能够实现每日万小时以上级别的持续数据采集与处理,不断为数据集注入鲜度,并保障了其持续扩展的能力。 简智机器人专注于通用具身智能全链路解决方案,为行业提供标准化、自动化的数据流基础设施服务。近日,简智机器人完成第三轮融资,成为具身智能数据基建细分赛道融资进展最快的企业。 「RealOmni」属于无本体具身数据集,这类数据集的核心是将数据采集的源头从「机器人」转移到了「人」,采集场景多,数据真实性高。传统数据集需要工作人员操作机器人,依赖机器人本体在特定环境(如实验室等)中运行获取数据,场景与机器人传感器性能受限、且数据维度少、精准度低。而无本体数据集的采集不依赖于特定机器人硬件,工作人员通过穿戴 GenDas 无感设备,

YOLO+OpenClaw+SAM微调实战:工业缺陷自动标注的低代码落地

YOLO+OpenClaw+SAM微调实战:工业缺陷自动标注的低代码落地

YOLO+OpenClaw+SAM微调实战:工业缺陷自动标注的低代码落地 不能实时,不代表不能用。微调SAM+云端部署,让工业标注从“人工描边”变“一键验收”。 大家好,我是AI小怪兽。上周有位做PCB质检的读者发来一段视频:标注员正对着一块电路板缺陷图,用鼠标一点点勾勒划痕的边界,一张图花了8分钟。他说:“YOLO能框,但框不准;SAM能分割,但通用模型到我们产线就水土不服。有没有办法让标注员少点鼠标?” 当然有。今天我就结合工业缺陷检测场景,展示一套低代码落地路径:YOLO粗定位 + 微调SAM精分割 + OpenClaw自动调度,让标注员从“动手画”变成“动口验收”。 一、工业自动标注的三道坎 坎1:OpenClaw无法实时推理 OpenClaw从接收指令到调用模型返回结果,5秒以上是常态。产线上的产品不可能等5秒,但标注任务可以——把数千张图丢给AI,让它半夜慢慢跑,员工早上来验收结果,不香吗? 坎2:边缘端算力要求大,且存在安全风险 OpenClaw调用大模型需要至少8GB显存,

【论文翻译】YOLO26: KEY ARCHITECTURAL ENHANCEMENTS AND PERFORMANCE BENCHMARKING FOR REAL-TIME OBJECT DETEC

【论文翻译】YOLO26: KEY ARCHITECTURAL ENHANCEMENTS AND PERFORMANCE BENCHMARKING FOR REAL-TIME OBJECT DETEC

YOLO26:实时目标检测的关键架构改进与性能基准测试 摘要 本研究对Ultralytics YOLO26进行了全面分析,重点阐述了其在实时边缘目标检测领域的关键架构改进与性能基准测试结果。YOLO26于2025年9月发布,是YOLO系列中最新、最先进的模型,专为在边缘设备和低功耗设备上实现高效能、高精度和部署就绪性而设计。论文依次详细介绍了YOLO26的架构创新,包括移除分布焦点损失(DFL)、采用端到端无非极大值抑制(NMS)推理、集成渐进式损失(ProgLoss)和小目标感知标签分配(STAL),以及引入MuSGD优化器以实现稳定收敛。除架构外,该研究将YOLO26定位为多任务框架,支持目标检测、实例分割、姿态/关键点估计、旋转检测和分类任务。我们在NVIDIA Jetson Nano和Orin等边缘设备上对YOLO26进行了性能基准测试,并将其结果与YOLOv8、YOLOv11、YOLOv12、YOLOv13以及基于Transformer的检测器进行了对比。论文进一步探讨了实时部署路径、灵活的导出选项(ONNX、TensorRT、CoreML、TFLite)以及INT8/