Spring Boot 实现防盗链功能

B站影视 2024-12-30 10:57 1

摘要:防盗链是保护资源服务器的常用方法,旨在防止未经授权的外部链接直接访问服务器上的资源,如图片、音频和视频文件。在本文中,我们将探讨防盗链的概念和原理,并结合 Spring Boot 提供一个完整的可运行示例。

防盗链是保护资源服务器的常用方法,旨在防止未经授权的外部链接直接访问服务器上的资源,如图片、音频和视频文件。在本文中,我们将探讨防盗链的概念和原理,并结合 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.jpegpackage 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;@SpringBootApplicationpublic class DemoApplication { public static void main(String args) { SpringApplication.run(DemoApplication.class, args); } @Bean public FilterRegistrationBean staticResourceFilter { FilterRegistrationBean registrationBean = new FilterRegistrationBean; registrationBean.setFilter(new StaticResourceFilter); registrationBean.addUrlPatterns("/images/*"); return registrationBean; }}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); }}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; }}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; }}

将一个图片文件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 校验、Token 验证和时间限制实现资源防盗链保护。如果有其他问题或需求,欢迎进一步探讨

来源:散文随风想一点号

相关推荐