Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 29 additions & 5 deletions base/src/main/java/com/tinyengine/it/common/utils/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ public class Utils {
*/
// 泛型去重方法
public static <T> List<T> removeDuplicates(List<T> list) {
if(list == null) {
return new ArrayList<>();
}
// 使用 Set 去重
Set<T> set = new LinkedHashSet<>(list);
// 返回去重后的 List
Expand Down Expand Up @@ -191,7 +194,7 @@ public static List<FileInfo> unzip(MultipartFile multipartFile) throws IOExcepti
* @return File the File
* @throws IOException IOException
*/
private static File createTempDirectory() throws IOException {
static File createTempDirectory() throws IOException {
return Files.createTempDirectory("unzip").toFile();
}

Expand All @@ -202,7 +205,7 @@ private static File createTempDirectory() throws IOException {
* @return File the File
* @throws IOException IOException
*/
private static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
File tempFile = File.createTempFile("temp", null);
tempFile.deleteOnExit();
try (FileOutputStream fos = new FileOutputStream(tempFile)) {
Expand All @@ -219,16 +222,37 @@ private static File convertMultipartFileToFile(MultipartFile multipartFile) thro
* @return List<FileInfo> the List<FileInfo>
* @throws IOException IOException
*/
private static List<FileInfo> processZipEntries(ZipInputStream zis, File tempDir) throws IOException {
static List<FileInfo> processZipEntries(ZipInputStream zis, File tempDir) throws IOException {
List<FileInfo> fileInfoList = new ArrayList<>();
ZipEntry zipEntry;

// 将 tempDir 转为规范路径(例如解析符号链接、父目录等)
Comment thread
hexqi marked this conversation as resolved.
Path safeDir = tempDir.toPath().toRealPath();
log.info("Created temporary directory at: {}, real path: {}", tempDir.getAbsolutePath(), safeDir);
while ((zipEntry = zis.getNextEntry()) != null) {

// 获取 ZIP 条目中的路径(可能包含 ../ 或绝对路径)
String entryName = zipEntry.getName();

// 拼接并规范化路径
Path targetPath = safeDir.resolve(entryName).normalize();

log.info("Processing ZIP entry: {}, target path: {}", entryName, targetPath);

// 关键校验:确保目标路径仍在 safeDir 之下
if (!targetPath.startsWith(safeDir)) {
throw new SecurityException("检测到跨目录攻击: " + entryName);
}
File newFile = new File(tempDir, zipEntry.getName());
Comment thread
chilingling marked this conversation as resolved.
Outdated

if (zipEntry.isDirectory()) {
// 创建目录(同时确保父目录存在)
Files.createDirectories(targetPath);
fileInfoList.add(new FileInfo(newFile.getName(), "", true)); // 添加目录
} else {
// 确保父目录存在
if(targetPath.getParent() != null) {
Files.createDirectories(targetPath.getParent());
}
extractFile(zis, newFile); // 解压文件
fileInfoList.add(new FileInfo(newFile.getName(), readFileContent(newFile), false)); // 添加文件内容
}
Expand Down Expand Up @@ -273,7 +297,7 @@ public static String readFileContent(File file) {
}

// 清理临时文件和目录
private static void cleanUp(File zipFile, File tempDir) {
static void cleanUp(File zipFile, File tempDir) {
// 删除临时的 zip 文件
if (zipFile.exists()) {
if (!zipFile.delete()) {
Expand Down
Loading
Loading