你想了解若依(RuoYi)框架的防盗链功能实现方式,我会从核心原理、代码实现、配置方式、关键细节四个维度拆解,兼顾原理理解和实操落地,适配若依单体版(RuoYi-Vue)和微服务版(RuoYi-Cloud)的通用逻辑。
若依最新前后端分离源码下载:
https://gitee.com/ruoyieleadmin/ruoyi-ele-admin
一、防盗链核心原理
若依框架的防盗链本质是基于 HTTP 协议的 Referer 头校验 + 白名单机制:
- Referer 头:HTTP 请求头中的
Referer字段会记录当前请求是从哪个页面跳转过来的(比如从 A 网站访问 B 网站的图片,B 网站能通过 Referer 看到请求来源是 A 网站); - 核心逻辑:服务器接收到静态资源(图片、文件、视频等)请求时,校验
Referer头是否在预设的白名单内(比如只允许自家域名访问),若不在则拒绝请求(返回 403 或重定向); - 补充场景:对无 Referer 的请求(如直接在浏览器输入资源 URL),可配置为 “允许” 或 “拒绝”,适配不同安全需求。
二、若依框架防盗链的具体实现(代码层面)
若依框架的防盗链功能集成在 Spring MVC 的拦截器 / 过滤器 中,核心代码在框架的 WebMvcConfig 或自定义的 Filter 类中,以下是关键实现步骤和代码:
1. 核心拦截器 / 过滤器实现(通用版)
若依通常通过 OncePerRequestFilter(过滤器,确保一次请求只执行一次)实现防盗链校验,核心代码如下(可直接复用):
java
运行
package com.ruoyi.framework.filter; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Arrays; import java.util.List; /** * 若依框架 防盗链过滤器 * 核心:校验Referer头,只允许白名单域名访问静态资源 */ @Component public class RefererFilter extends OncePerRequestFilter { /** * 防盗链白名单(配置在application.yml中,多个域名用逗号分隔) * 示例:ruoyi.com,localhost:8080,127.0.0.1:8080 */ @Value("${ruoyi.antiHotlink.allowReferer:}") private String allowReferer; /** * 需要拦截的资源后缀(静态资源) */ private static final List<String> INTERCEPT_SUFFIX = Arrays.asList(".jpg", ".png", ".gif", ".mp4", ".pdf", ".docx"); @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 1. 获取请求URL,判断是否为需要拦截的静态资源 String requestURI = request.getRequestURI().toLowerCase(); boolean isIntercept = INTERCEPT_SUFFIX.stream().anyMatch(requestURI::endsWith); if (!isIntercept) { // 非静态资源,直接放行 filterChain.doFilter(request, response); return; } // 2. 解析白名单 List<String> allowList = Arrays.asList(allowReferer.split(",")); if (allowList.isEmpty()) { // 白名单为空,直接放行(或根据需求返回403) filterChain.doFilter(request, response); return; } // 3. 获取Referer头 String referer = request.getHeader("Referer"); if (referer == null || referer.isEmpty()) { // 无Referer请求(直接访问资源URL),可配置为放行/拒绝 // 此处示例:拒绝无Referer的请求 response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.getWriter().write("403 Forbidden: 非法访问(无Referer)"); return; } // 4. 校验Referer是否在白名单内 boolean isAllow = allowList.stream().anyMatch(referer::contains); if (isAllow) { // 合法来源,放行 filterChain.doFilter(request, response); } else { // 非法来源,返回403 response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.getWriter().write("403 Forbidden: 非法访问(防盗链拦截)"); } } }
2. 若依框架默认配置(application.yml)
在 application.yml 中添加防盗链白名单配置,与上述过滤器关联:
yaml
ruoyi: # 防盗链配置 antiHotlink: # 允许的Referer白名单(多个域名用逗号分隔) allowReferer: "ruoyi.com,localhost:8080,127.0.0.1:8080,192.168.1.0/24"
3. 注册过滤器(关键步骤)
若依框架需将上述过滤器注册到 Spring 容器,通常在 WebConfig 类中配置(若依单体版的 WebMvcConfig 已集成类似逻辑):
java
运行
package com.ruoyi.framework.config; import com.ruoyi.framework.filter.RefererFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 过滤器注册配置 */ @Configuration public class FilterConfig { @Autowired private RefererFilter refererFilter; /** * 注册防盗链过滤器 */ @Bean public FilterRegistrationBean<RefererFilter> refererFilterRegistration() { FilterRegistrationBean<RefererFilter> registration = new FilterRegistrationBean<>(); registration.setFilter(refererFilter); // 拦截所有请求(后续在过滤器内筛选静态资源) registration.addUrlPatterns("/*"); // 过滤器名称 registration.setName("refererFilter"); // 执行顺序(数字越小,执行越早) registration.setOrder(1); return registration; } }
三、若依微服务版(RuoYi-Cloud)的特殊处理
微服务版的防盗链逻辑与单体版一致,但需注意:
- 拦截位置:建议在网关(Gateway)层实现防盗链,而非每个业务模块,避免重复校验;
- 网关层实现:通过 Gateway 的
GlobalFilter替代OncePerRequestFilter,核心逻辑不变,只是适配网关的 API:
java
运行
@Component public class GatewayRefererFilter implements GlobalFilter, Ordered { @Value("${ruoyi.antiHotlink.allowReferer:}") private String allowReferer; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String requestURI = request.getPath().value().toLowerCase(); // 1. 校验资源类型(同单体版) // 2. 获取Referer(网关层获取请求头的方式) String referer = request.getHeaders().getFirst("Referer"); // 3. 白名单校验(逻辑同单体版) // 4. 放行/拒绝(网关层拒绝请求的方式) if (!isAllow) { ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.FORBIDDEN); return response.setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return 1; // 执行顺序 } }
四、关键细节与优化
- 白名单配置技巧:
- 支持通配符:如
*.ruoyi.com匹配所有子域名(需在代码中处理通配符逻辑); - 支持 IP 段:如
192.168.1.0/24匹配整个网段; - 本地开发时,务必将
localhost:8080、127.0.0.1:8080加入白名单,避免本地调试被拦截。
- 例外场景处理:
- 对 API 接口(如
/api/**)无需拦截,只拦截静态资源(.jpg/.png/.mp4等); - 对后台管理系统的资源(如
/static/**),可单独放行,避免误拦截。
- 绕过 Referer 的应对:
- 部分恶意请求会伪造 Referer 头,可结合
IP 白名单、Token 校验增强防护; - 对高价值资源(如付费视频),可添加
签名校验(如 URL 带时效签名),仅靠 Referer 不够。
- 若依框架默认是否开启:
- 若依基础版未默认开启防盗链,需手动添加上述过滤器和配置;
- 若依增强版 / 企业版可能已集成防盗链功能,可在
application.yml中直接配置白名单启用。
总结
若依框架的防盗链核心是:
- 核心机制:基于 HTTP Referer 头的白名单校验,通过过滤器拦截静态资源请求;
- 实现方式:单体版用
OncePerRequestFilter,微服务版在网关层用GlobalFilter; - 关键配置:在
application.yml中配置允许的 Referer 白名单,按需拦截指定后缀的静态资源; - 优化建议:生产环境需结合 IP 白名单、签名校验,避免仅依赖 Referer 导致防护失效。