安全解压zip需防止路径遍历和zip bomb:规范化并校验条目路径是否在目标目录内;限制条目数、单文件大小及总读取量;过滤非法文件名;用try-with-resources确保资源关闭并清理临时文件。

使用 ZipInputStream 安全解压 ZIP 文件,核心是防止路径遍历(如 ../../etc/passwd)和拒绝服务攻击(如 ZIP bomb)。Java 原生不自动校验路径安全性,必须手动检查。
校验 ZIP 条目路径,阻止目录穿越
每次调用 getNextEntry() 后,必须规范化条目路径,并确保其不脱离目标解压目录:
- 用
ZipEntry.getName()获取原始路径 - 调用
Paths.get(entryName).normalize()消除..和. - 检查规范化后路径是否仍以目标目录为前缀(推荐用
startsWith(Paths.get(targetDir).toAbsolutePath())) - 拒绝任何含
".."、以"/"开头、或含控制字符的路径
限制解压内容大小与条目数量
防止 ZIP bomb(恶意超大/超多小文件压缩包)导致内存耗尽或磁盘写满:
用于 inference.sh 的 JavaScript/TypeScript SDK,可运行 AI 应用、构建代理、集成 150+ 模型。包名:@inferencesh/sdk(npm install),完整 TypeScript 支持。
- 在循环读取每个条目前,检查
entry.getSize()(若为 -1,可跳过或设上限如 100MB) - 维护已处理条目计数,超过阈值(如 10000)直接抛异常终止
- 对单个文件流读取时,使用带缓冲的
byte[](如 8KB),并累计已读字节数,超限时中断
避免创建非法文件系统对象
ZIP 条目可能包含特殊名称(如 NUL、CON、AUX 等 Windows 设备名,或空名、仅空格名):
- 过滤掉
entry.getName().trim().isEmpty()的条目 - 对 Windows 系统,拒绝匹配
^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])$(忽略大小写)的文件名(不含扩展名) - 拒绝含
\0、/(作为文件名一部分)、控制字符(U+0000–U+001F)的名称 - 建议将文件名转为合法 ASCII 或 UTF-8 安全编码(如用
URLEncoder.encode(name, "UTF-8")替换非法字符)
正确关闭资源并处理异常
ZipInputStream 必须显式关闭,且需在 finally 或 try-with-resources 中完成:
- 使用 try-with-resources 包裹
ZipInputStream和底层FileInputStream - 捕获
IOException、SecurityException(路径校验失败时主动抛出)和ZipException(损坏 ZIP) - 解压过程中任一异常都应立即停止,并删除已写入的临时文件(可借助
Files.createTempDirectory预先建隔离目录)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










