基于SpringBoot实现防盗链功能

 更新时间:2024年12月16日 17:11:05   作者: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&timestamp=$(date +%s)" -H "Referer: http://localhost:8088"
  • 检查以下情况:

    • 如果 Referer 不正确,返回 403 Forbidden: Hotlinking not allowed
    • 如果 Token 无效,返回 403 Forbidden: Invalid Token
    • 如果时间戳超时,返回 403 Forbidden: Timestamp Expired

通过本文,您可以了解如何通过 Referer 校验、Token 验证和时间限制实现资源防盗链保护。如果有其他问题或需求,欢迎进一步探讨!

到此这篇关于基于SpringBoot实现防盗链功能的文章就介绍到这了,更多相关SpringBoot防盗链内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot 1.5.2 集成kafka的简单例子

    springboot 1.5.2 集成kafka的简单例子

    本篇文章主要介绍了springboot 1.5.2 集成kafka的简单例子 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • MyBatis逆向工程的创建和使用

    MyBatis逆向工程的创建和使用

    这篇文章主要介绍了MyBatis逆向工程的创建和使用,需要的朋友可以参考下
    2017-08-08
  • java实现倾斜水印铺满整张图

    java实现倾斜水印铺满整张图

    这篇文章主要为大家详细介绍了java实现倾斜水印铺满整张图的具体代码,教大家如何控制水印之间的空隙,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • gateway和jwt网关认证实现过程解析

    gateway和jwt网关认证实现过程解析

    这篇文章主要介绍了gateway和jwt网关认证实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • Java Stream 流实现合并操作示例

    Java Stream 流实现合并操作示例

    这篇文章主要介绍了Java Stream 流实现合并操作,结合实例形式详细分析了Java Stream 流实现合并操作原理与相关注意事项,需要的朋友可以参考下
    2020-05-05
  • SpringBoot如何读取xml配置bean(@ImportResource)

    SpringBoot如何读取xml配置bean(@ImportResource)

    这篇文章主要介绍了SpringBoot如何读取xml配置bean(@ImportResource),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • 详解java关于对象的比较

    详解java关于对象的比较

    这篇文章主要为大家介绍了java关于对象的比较,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-01-01
  • java字符串求并集的方法

    java字符串求并集的方法

    这篇文章主要介绍了java字符串求并集的方法,涉及Java字符串操作中union方法的使用,是Java字符串操作中非常实用的基本技巧,需要的朋友可以参考下
    2014-11-11
  • Spring框架概述及核心设计思想分享

    Spring框架概述及核心设计思想分享

    Spring框架是一种开源的Java企业级应用开发框架,提供了IoC(控制反转)容器和DI(依赖注入)等核心设计思想,SpringBoot则是在Spring基础上进一步简化配置,提供了快速开发、内置服务器等功能,学习Spring框架需要掌握容器、IoC和DI等概念,以及分层设计等软件工程思想
    2025-02-02
  • Kafka是什么及如何使用SpringBoot对接Kafka(最新推荐)

    Kafka是什么及如何使用SpringBoot对接Kafka(最新推荐)

    这篇文章主要介绍了Kafka是什么,以及如何使用SpringBoot对接Kafka,今天我们通过一个Demo讲解了在SpringBoot中如何对接Kafka,也介绍了下关键类 KafkaTemplate,需要的朋友可以参考下
    2023-11-11

最新评论