java超长文本与二进制流防御须前置到协议层和io层:文本需校验content-length、流式解析并按utf-8字节计数;二进制流要配置multipart限制、手动读取时实时计数;网关层(nginx/gateway)必须统一设限。

Java 中对超长文本与二进制流的长度防御,不能只靠注解层面的 @Size 或 @Max,因为这些校验器在 Spring Validation 中默认作用于对象字段,而文本可能尚未解析(如 JSON body 未反序列化),二进制流(如 MultipartFile 或原始 InputStream)更无法被标准 Bean Validation 处理——它根本不是“Bean 字段”,而是 HTTP 请求体的一部分。真正的防御必须前置到协议层和 IO 层。
对超长文本:拦截未解析的原始字节流
攻击者可构造超大 JSON、XML 或表单文本绕过字段级校验。例如一个 content 字段声明为 @Size(max = 10000),但若请求体本身是 50MB 的 JSON,服务在反序列化前就已耗尽内存或触发 OOM。
- 使用 Spring 的
ContentLengthLimitingRequestWrapper或自定义OncePerRequestFilter,在请求进入 DispatcherServlet 前检查Content-Length头,拒绝超过阈值(如 10MB)的请求 - 对 JSON 接口,配置 Jackson 的
JsonFactory.Feature.FAIL_ON_BIG_DECIMALS和DeserializationFeature.FAIL_ON_TRAILING_TOKENS,并启用流式解析(JsonParser)逐段读取,配合字符计数器实时中断超长字符串字段 - 避免将整个请求体加载为
String;改用InputStreamReader+BufferedReader按行/按块读取,并在每块内统计 UTF-8 字节数(非String.length()),防止代理层编码混淆
对二进制流:绕过内存缓冲,直控输入流边界
MultipartFile 默认会将小文件存入内存(StandardMultipartHttpServletRequest 使用 ByteArrayMultipartFile),大文件才落盘。但攻击者可上传 1GB 空白文件或恶意分块流,导致磁盘写满或临时目录阻塞。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 在
application.properties中强制限制:
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=15MB
注意:该配置仅对 Spring MVC 有效,若用 WebFlux 或直接处理InputStream,需另行控制 - 对于手动读取
HttpServletRequest.getInputStream()的场景(如对接微信二维码接口),必须在读取循环中累计字节数,一旦超出预设上限(如 2MB 图片流),立即关闭流并返回 413 Payload Too Large - 不要依赖
multipart/form-data解析后的MultipartFile.getSize()做唯一判断——该值可能被伪造或延迟计算;应在解析 multipart boundary 过程中,对每个 part 的 header 和 body 分别做长度扫描
统一网关层兜底:避免框架盲区
即使应用层做了双重校验,微服务架构下仍存在网关(如 Spring Cloud Gateway、Nginx)未设限的风险。Nginx 默认 client_max_body_size 是 1MB,不显式配置会导致 413 错误发生在网关而非业务服务,掩盖真实问题。
- Nginx 配置示例:
client_max_body_size 10m;
client_header_timeout 60;
client_body_timeout 60; - Spring Cloud Gateway 可通过
ServerWebExchange的getFormData()或getMultipartData()获取流,结合ReactiveAdapter实现响应式流长度采样,配合Resilience4j设置熔断阈值 - 所有上传入口(含 Swagger UI、Actuator endpoints)都应纳入统一限流策略,防止绕过主 Controller 路径
关键不在“校验”,而在“截断”——长度防御的本质是尽早丢弃非法字节,不让它们进入应用内存或磁盘。文本看字节数,流看读取量,网关看 header,三者缺一不可。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










