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

图片防盗链技术是通过限制外部站点非法引用自己服务器上的资源,防止盗用带宽及流量,并保护版权和服务器资源。特别是当你的网站中包含大量图片资源时,如果不采取防盗链措施,其他网站可能会直接引用你的图片,而你却为这些图片的展示支付流量费用。为了防止盗链,常用的技术手段是基于HTTP请求头的Referer字段。

本文将详细阐述图片防盗链的原理,并给出基于Spring Boot实现防盗链的解决方案。


一、防盗链原理分析

1. Referer头的原理

Referer 是 HTTP 请求头的一部分,表示当前请求页面的来源URL。网站服务器可以通过读取这个字段来判断请求是否来自自己的网站。如果请求的图片或资源来自非法来源(即非授权的站点),就可以拒绝提供资源。

  • 合法请求:当图片被正确地从自己的站点加载时,Referer 头会包含该站点的域名。
  • 非法请求:如果其他站点直接引用图片,Referer 头会显示那个站点的域名,这时候服务器就可以根据Referer来判断请求是否是非法的。

2. 防盗链流程

  1. 用户在浏览器中请求图片资源。
  2. 浏览器自动附加Referer头,向图片服务器发起请求。
  3. 服务器检查Referer头,如果请求来自合法网站,则返回图片;如果请求来自非法网站,则返回错误信息(例如403 Forbidden)。

二、Spring Boot实现图片防盗链

1. 配置Spring Boot应用

在Spring Boot中,我们可以通过自定义过滤器来拦截HTTP请求,检查Referer头,从而判断是否是合法的请求。

步骤:

  1. 创建一个过滤器(Filter),在过滤器中检查HTTP请求的Referer头。
  2. 如果Referer合法,继续响应请求,否则返回403 Forbidden错误。

2. 自定义过滤器

首先,需要创建一个过滤器类来处理防盗链逻辑:

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter(filterName = "refererFilter", urlPatterns = "/images/*") // 监听图片资源请求
public class RefererFilter implements Filter {

    // 白名单域名
    private static final String[] ALLOWED_REFERERS = {
        "https://www.yourwebsite.com",
        "https://www.other-allowed-site.com"
    };

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作,可以不做任何处理
    }

    @Override
    public void doFilter(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 获取Referer头
        String referer = httpRequest.getHeader("Referer");

        if (referer == null || !isAllowedReferer(referer)) {
            // 非法Referer,返回403
            httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
            httpResponse.getWriter().write("Forbidden: You are not allowed to access this resource.");
            return;
        }

        // 合法Referer,继续执行请求
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 清理操作,可以不做任何处理
    }

    // 判断Referer是否在允许的白名单中
    private boolean isAllowedReferer(String referer) {
        for (String allowedReferer : ALLOWED_REFERERS) {
            if (referer.startsWith(allowedReferer)) {
                return true;
            }
        }
        return false;
    }
}

在上面的代码中:

  • urlPatterns = "/images/*":表示只对 /images/ 路径下的图片资源进行防盗链处理。
  • ALLOWED_REFERERS:存储合法站点的白名单,只有在这个白名单中的站点,才可以访问图片资源。
  • doFilter 方法中判断请求的Referer是否合法,如果合法,继续处理请求;如果非法,返回403错误。

3. 注册过滤器

在Spring Boot中,过滤器需要注册才能生效。你可以通过配置类将过滤器注册到应用中。

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<RefererFilter> refererFilter() {
        FilterRegistrationBean<RefererFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new RefererFilter());
        registrationBean.addUrlPatterns("/images/*"); // 只拦截/images/*路径下的图片请求
        return registrationBean;
    }
}

4. 启动并测试

  • 启动Spring Boot应用,确保过滤器已正确注册。
  • 访问图片时,从合法网站请求资源,将会成功返回图片。
  • 从非法网站请求资源,将返回403 Forbidden错误。

三、优化与扩展

1. 动态配置白名单

有时候白名单需要动态配置,而不是在代码中硬编码。你可以将白名单存储在数据库或配置文件中,在过滤器中读取。

private List<String> allowedReferers;

public RefererFilter() {
    // 从配置文件或数据库加载白名单
    this.allowedReferers = loadAllowedReferers();
}

private List<String> loadAllowedReferers() {
    // 从配置文件、数据库或其他存储加载白名单
    return Arrays.asList("https://www.yourwebsite.com", "https://www.other-allowed-site.com");
}

2. 设置缓存和其他防盗链策略

除了Referer防盗链,还有其他防盗链策略,例如:

  • 使用Token认证:在URL中附加唯一的Token,通过Token判断请求是否合法。
  • 限制IP访问:通过X-Forwarded-ForRemoteAddr限制访问的IP范围。

3. 提高性能

每次请求都需要检查Referer头可能会带来性能问题,尤其是对于高流量的站点。你可以通过以下方式提高性能:

  • 使用缓存存储合法Referer
  • 使用CDN加速图片的请求,同时支持防盗链设置。

四、总结

本文介绍了图片防盗链的基本原理及其实现方式,通过Spring Boot应用自定义过滤器来实现基于Referer头的防盗链机制,防止其他站点非法引用你网站的图片资源。通过此方式,你可以有效保护网站资源、节约带宽,并保障版权。同时,还介绍了如何扩展和优化防盗链机制,例如动态配置白名单和设置其他防盗链策略。