You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring应用中实现Length hiding以防御BREACH攻击?

在Spring应用中实现长度隐藏(Length Hiding)缓解BREACH攻击

BREACH攻击利用压缩后的响应长度变化窃取敏感信息,长度隐藏通过向响应末尾添加随机数字节干扰攻击者的长度分析,是有效的缓解手段之一。以下是Spring应用中的具体实现方案:

方法一:自定义Servlet Filter拦截并修改响应

1. 实现响应包装类

创建HttpServletResponseWrapper子类,用于捕获响应内容并添加随机字节:

import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.WriteListener;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;

public class LengthHidingResponseWrapper extends HttpServletResponseWrapper {
    private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    private PrintWriter writer;
    private final Random random = new Random();

    public LengthHidingResponseWrapper(HttpServletResponse response) {
        super(response);
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return new ServletOutputStream() {
            @Override
            public void write(int b) throws IOException {
                buffer.write(b);
            }

            @Override
            public boolean isReady() {
                return true;
            }

            @Override
            public void setWriteListener(WriteListener writeListener) {
                // 无需额外实现
            }
        };
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        if (writer == null) {
            writer = new PrintWriter(buffer);
        }
        return writer;
    }

    @Override
    public void flushBuffer() throws IOException {
        // 生成1-100个随机字节,可根据需求调整范围
        int randomByteCount = random.nextInt(100) + 1;
        byte[] randomBytes = new byte[randomByteCount];
        random.nextBytes(randomBytes);
        buffer.write(randomBytes);

        // 将修改后的内容写入原始响应
        ServletOutputStream out = getResponse().getOutputStream();
        out.write(buffer.toByteArray());
        out.flush();
        buffer.reset();
    }
}

2. 实现自定义Filter

创建OncePerRequestFilter子类,拦截请求并应用响应包装:

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

public class LengthHidingFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 仅对文本类型响应生效,避免破坏二进制内容(如图片、文件)
        String contentType = response.getContentType();
        if (contentType != null && (contentType.contains("text/html") || contentType.contains("application/json"))) {
            LengthHidingResponseWrapper wrappedResponse = new LengthHidingResponseWrapper(response);
            filterChain.doFilter(request, wrappedResponse);
            wrappedResponse.flushBuffer();
        } else {
            filterChain.doFilter(request, response);
        }
    }
}

3. 注册Filter到Spring容器

在Spring Boot中通过配置类完成注册:

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

@Configuration
public class LengthHidingConfig {
    @Bean
    public FilterRegistrationBean<LengthHidingFilter> lengthHidingFilter() {
        FilterRegistrationBean<LengthHidingFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new LengthHidingFilter());
        // 拦截所有路径,可根据业务调整
        registrationBean.addUrlPatterns("/*");
        // 设置优先级,确保在响应压缩等过滤器之前执行
        registrationBean.setOrder(1);
        return registrationBean;
    }
}

关键注意事项

  • 避免破坏二进制内容:必须判断响应的Content-Type,仅对HTML、JSON等文本类型添加随机字节,否则会导致图片、文件下载等内容损坏。
  • 压缩兼容性:如果应用启用了响应压缩(如Gzip),需确保Length Hiding Filter在压缩过滤器之前执行,否则随机字节会被压缩,无法起到干扰长度的作用;也可直接禁用响应压缩作为替代方案。
  • 随机字节范围:随机字节数量不宜过大(避免影响响应性能)或过小(无法有效干扰攻击者),推荐1-100字节的范围。

内容的提问来源于stack exchange,提问作者NVJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 18:51:19