gushoubang il y a 2 mois
Parent
commit
ceaabda8d5

+ 33 - 20
siwei-modules/siwei-spatial/src/main/java/com/siwei/spatial/utils/FileUtils.java

@@ -7,52 +7,52 @@ import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.util.*;
 import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
 import java.util.zip.ZipFile;
 
 /**
  * 文件工具类
  */
 public class FileUtils {
+
     /**
-     * 解压缩zip文件到指定目录
-     *
-     * @param zipFilePath
-     * @param destDir
-     * @throws IOException
+     * 解压ZIP文件,自动尝试UTF-8和GBK编码
      */
     public static void unzipAutoCharset(String zipFilePath, String destDir) throws IOException {
         try {
-            // 先尝试 UTF-8
             unzipWithCharset(zipFilePath, destDir, Charset.forName("UTF-8"));
-        } catch (IllegalArgumentException | java.nio.charset.MalformedInputException e) {
-            // 如果失败,切换到 GBK
+        } catch (ZipException e) { // 捕获ZIP结构或编码问题
             unzipWithCharset(zipFilePath, destDir, Charset.forName("GBK"));
         }
     }
 
     /**
-     * 解压缩zip文件到指定目录,使用指定字符集
-     *
-     * @param zipFilePath
-     * @param destDir
-     * @param charset
-     * @throws IOException
+     * 按指定字符集解压ZIP文件
      */
     private static void unzipWithCharset(String zipFilePath, String destDir, Charset charset) throws IOException {
         File dir = new File(destDir);
-        if (!dir.exists()) dir.mkdirs();
+        if (!dir.exists() && !dir.mkdirs()) {
+            throw new IOException("无法创建目录: " + destDir);
+        }
 
         try (ZipFile zipFile = new ZipFile(zipFilePath, charset)) {
             Enumeration<? extends ZipEntry> entries = zipFile.entries();
             while (entries.hasMoreElements()) {
                 ZipEntry entry = entries.nextElement();
-                File newFile = new File(destDir, entry.getName());
+                File newFile = safeNewFile(dir, entry.getName()); // 安全路径拼接
+
                 if (entry.isDirectory()) {
-                    newFile.mkdirs();
+                    if (!newFile.exists() && !newFile.mkdirs()) {
+                        throw new IOException("无法创建目录: " + newFile);
+                    }
                 } else {
-                    new File(newFile.getParent()).mkdirs();
-                    try (InputStream is = zipFile.getInputStream(entry); FileOutputStream fos = new FileOutputStream(newFile)) {
-                        byte[] buffer = new byte[1024];
+                    File parent = newFile.getParentFile();
+                    if (!parent.exists() && !parent.mkdirs()) {
+                        throw new IOException("无法创建文件目录: " + parent);
+                    }
+                    try (InputStream is = zipFile.getInputStream(entry);
+                         FileOutputStream fos = new FileOutputStream(newFile)) {
+                        byte[] buffer = new byte[4096];
                         int len;
                         while ((len = is.read(buffer)) > 0) {
                             fos.write(buffer, 0, len);
@@ -63,6 +63,19 @@ public class FileUtils {
         }
     }
 
+    /**
+     * 防止Zip Slip漏洞:限制文件解压在目标目录内
+     */
+    private static File safeNewFile(File destinationDir, String entryName) throws IOException {
+        File destFile = new File(destinationDir, entryName);
+        String destDirPath = destinationDir.getCanonicalPath();
+        String destFilePath = destFile.getCanonicalPath();
+        if (!destFilePath.startsWith(destDirPath + File.separator)) {
+            throw new IOException("非法ZIP条目: " + entryName);
+        }
+        return destFile;
+    }
+
     /**
      * 读取文件夹中及子文件夹中的所有shp相关文件(.shp,.dbf,.prj,.qix,.shx),返回map结构,后缀名为key,文件路径为value
      *