基于SpringBoot实现防盗链功能
作者:HBLOG
防盗链是保护资源服务器的常用方法,旨在防止未经授权的外部链接直接访问服务器上的资源,如图片、音频和视频文件,在本文中,我们将探讨防盗链的概念和原理,并结合 Spring Boot 提供一个完整的可运行示例,需要的朋友可以参考下
一、防盗链概念
防盗链是一种通过限制资源访问来源的技术,通常通过检查 HTTP 请求头中的 Referer
字段来实现。如果请求的来源不是允许的域名,则拒绝该请求。除此之外,还可以结合 Token
和时间戳进一步提高安全性,确保链接只能在一定时间内有效。
二、防盗链原理
- Referer 校验:
- HTTP Referer 是浏览器在发送请求时附加的字段,用于标明请求的来源页面。
- 服务器可以通过检查 Referer 是否属于信任的域名,拒绝其他来源的访问请求。
- Token 验证:
- 服务器为合法请求生成带签名的访问链接(包含 Token),客户端访问时携带该 Token。
- 服务器通过验证 Token 是否正确来判断请求合法性。
- 时间限制:
- 通过在请求中附带时间戳参数,限制链接的有效期。
- 服务器校验请求的时间戳与当前时间的差值,超出范围的请求将被拒绝。
通过以上三种机制,可以显著提高资源防盗链的安全性。
三、项目结构
以下是示例项目的目录结构:
src ├── main │ ├── java │ │ └── com.demo │ │ ├── DemoApplication.java │ │ ├── filter │ │ │ ├── StaticResourceFilter.java │ │ │ ├── TokenValidator.java │ │ │ └── TimeValidator.java │ └── resources │ └── static │ └── images └──711815.jpeg
四、核心代码实现
1. 主应用程序入口
package com.et; import com.et.filter.StaticResourceFilter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Bean public FilterRegistrationBean<StaticResourceFilter> staticResourceFilter() { FilterRegistrationBean<StaticResourceFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new StaticResourceFilter()); registrationBean.addUrlPatterns("/images/*"); return registrationBean; } }
2. 静态资源访问过滤器
package com.et.filter; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class StaticResourceFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; // validate Referer String referer = httpRequest.getHeader("Referer"); String allowedDomain = "http://localhost:8088"; if (referer == null || !referer.startsWith(allowedDomain)) { httpResponse.getWriter().write("403 Forbidden: Hotlinking not allowed"); return; } // validate Token if (!TokenValidator.validateToken(httpRequest, httpResponse)) { return; } // validate Timestamp if (!TimeValidator.validateTimestamp(httpRequest, httpResponse)) { return; } chain.doFilter(request, response); } }
3. Token 验证工具
package com.et.filter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class TokenValidator { public static boolean validateToken(HttpServletRequest request, HttpServletResponse response) throws IOException { String token = request.getParameter("token"); String validToken = "your-predefined-token"; //set your predefined token here if (token == null || !token.equals(validToken)) { response.getWriter().write("403 Forbidden: Invalid Token"); return false; } return true; } }
4. 时间限制验证工具
package com.et.filter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.time.Instant; public class TimeValidator { private static final long ALLOWED_TIME_DIFF = 300; // offset in seconds( 300 seconds) public static boolean validateTimestamp(HttpServletRequest request, HttpServletResponse response) throws IOException { String timestampStr = request.getParameter("timestamp"); if (timestampStr == null) { response.getWriter().write("403 Forbidden: Missing Timestamp"); return false; } try { long timestamp = Long.parseLong(timestampStr); long currentTimestamp = Instant.now().getEpochSecond(); if (Math.abs(currentTimestamp - timestamp) > ALLOWED_TIME_DIFF) { response.getWriter().write("403 Forbidden: Timestamp Expired"); return false; } } catch (NumberFormatException e) { response.getWriter().write("403 Forbidden: Invalid Timestamp"); return false; } return true; } }
5. 静态资源示例
将一个图片文件711815.jpeg
放入 src/main/resources/static/images
文件夹中。
以上只是一些关键代码。
五、测试方式
启动 Spring Boot 项目。
测试访问图片资源:
curl -X GET "http://localhost:8088/static/example.jpg?token=your-predefined-token×tamp=$(date +%s)" -H "Referer: http://localhost:8088"
检查以下情况:
- 如果 Referer 不正确,返回
403 Forbidden: Hotlinking not allowed
。 - 如果 Token 无效,返回
403 Forbidden: Invalid Token
。 - 如果时间戳超时,返回
403 Forbidden: Timestamp Expired
。
- 如果 Referer 不正确,返回
通过本文,您可以了解如何通过 Referer 校验、Token 验证和时间限制实现资源防盗链保护。如果有其他问题或需求,欢迎进一步探讨!
到此这篇关于基于SpringBoot实现防盗链功能的文章就介绍到这了,更多相关SpringBoot防盗链内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!