diff --git a/smart-admin-api-java17-springboot3/pom.xml b/smart-admin-api-java17-springboot3/pom.xml
index 6de337d3..212f55df 100644
--- a/smart-admin-api-java17-springboot3/pom.xml
+++ b/smart-admin-api-java17-springboot3/pom.xml
@@ -57,6 +57,7 @@
2.2
2.3.33
1.18.1
+ 3.1.0
@@ -325,6 +326,12 @@
${freemarker.version}
+
+ org.apache.tika
+ tika-core
+ ${tika.version}
+
+
@@ -414,4 +421,4 @@
-
\ No newline at end of file
+
diff --git a/smart-admin-api-java17-springboot3/sa-base/pom.xml b/smart-admin-api-java17-springboot3/sa-base/pom.xml
index 75c32c3b..97920440 100644
--- a/smart-admin-api-java17-springboot3/sa-base/pom.xml
+++ b/smart-admin-api-java17-springboot3/sa-base/pom.xml
@@ -273,7 +273,12 @@
freemarker
+
+ org.apache.tika
+ tika-core
+
+
-
\ No newline at end of file
+
diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityFileService.java b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityFileService.java
index 6774a43c..5a0117e3 100644
--- a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityFileService.java
+++ b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityFileService.java
@@ -2,10 +2,19 @@ package net.lab1024.sa.base.module.support.securityprotect.service;
import jakarta.annotation.Resource;
import net.lab1024.sa.base.common.domain.ResponseDTO;
+import org.apache.tika.config.TikaConfig;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaCoreProperties;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.mime.MimeTypes;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
-import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
/**
* 三级等保 文件上传 相关
@@ -23,6 +32,28 @@ public class SecurityFileService {
@Resource
private Level3ProtectConfigService level3ProtectConfigService;
+ // 定义白名单MIME类型
+ private static final List ALLOWED_MIME_TYPES = Arrays.asList(
+ "application/json",
+ "application/zip",
+ "application/x-7z-compressed",
+ "application/pdf",
+ "application/vnd.ms-excel",
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ "application/vnd.ms-powerpoint",
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+ "application/msword",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ "application/vnd.ms-works",
+ "text/csv",
+ "audio/*",
+ "video/*",
+ // 图片类型 svg有安全隐患,所以不使用"image/*"
+ "image/jpeg",
+ "image/png",
+ "image/gif",
+ "image/bmp"
+ );
/**
* 检测文件安全类型
@@ -38,15 +69,50 @@ public class SecurityFileService {
}
// 文件类型安全检测
- if (!level3ProtectConfigService.isFileDetectFlag()) {
- return ResponseDTO.ok();
+ if (level3ProtectConfigService.isFileDetectFlag()) {
+ String fileType = getFileMimeType(file);
+ if(ALLOWED_MIME_TYPES.stream()
+ .noneMatch(allowedType -> matchesMimeType(fileType, allowedType))){
+ return ResponseDTO.userErrorParam("禁止上传此文件类型");
+ }
}
- // 检测文件类型
- // .....
-
return ResponseDTO.ok();
}
+ /**
+ * 获取文件的 MIME 类型
+ *
+ * @param file 要检查的文件
+ * @return 文件的 MIME 类型
+ *
+ */
+ public static String getFileMimeType(MultipartFile file) {
+ try {
+ TikaConfig tika = new TikaConfig();
+ Metadata metadata = new Metadata();
+ metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, file.getOriginalFilename());
+ TikaInputStream stream = TikaInputStream.get(file.getInputStream());
+ MediaType mimetype = tika.getDetector().detect(stream, metadata);
+ return mimetype.toString();
+ } catch (IOException | TikaException e) {
+ return MimeTypes.OCTET_STREAM;
+ }
+ }
+
+ /**
+ * 检查文件的 MIME 类型是否与指定的MIME 类型匹配(支持通配符)
+ *
+ * @param fileType 文件的 MIME 类型
+ * @param mimetype MIME 类型(支持通配符)
+ * @return 是否匹配
+ */
+ private static boolean matchesMimeType(String fileType, String mimetype) {
+ if (mimetype.endsWith("/*")) {
+ String prefix = mimetype.substring(0, mimetype.length() - 1);
+ return fileType.startsWith(prefix);
+ } else {
+ return fileType.equalsIgnoreCase(mimetype);
+ }
+ }
}
-;
\ No newline at end of file
diff --git a/smart-admin-api-java8-springboot2/pom.xml b/smart-admin-api-java8-springboot2/pom.xml
index f861e07e..f0567b0f 100644
--- a/smart-admin-api-java8-springboot2/pom.xml
+++ b/smart-admin-api-java8-springboot2/pom.xml
@@ -59,6 +59,7 @@
2.2
2.3.33
1.18.1
+ 2.9.3
@@ -370,6 +371,12 @@
${freemarker.version}
+
+ org.apache.tika
+ tika-core
+ ${tika.version}
+
+
diff --git a/smart-admin-api-java8-springboot2/sa-base/pom.xml b/smart-admin-api-java8-springboot2/sa-base/pom.xml
index 3c43d462..b85edb17 100644
--- a/smart-admin-api-java8-springboot2/sa-base/pom.xml
+++ b/smart-admin-api-java8-springboot2/sa-base/pom.xml
@@ -303,6 +303,11 @@
freemarker
+
+ org.apache.tika
+ tika-core
+ ${tika.version}
+
diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityFileService.java b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityFileService.java
index cdea03a4..cd1190a5 100644
--- a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityFileService.java
+++ b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityFileService.java
@@ -1,11 +1,23 @@
package net.lab1024.sa.base.module.support.securityprotect.service;
import net.lab1024.sa.base.common.domain.ResponseDTO;
+import org.apache.tika.config.TikaConfig;
+import org.apache.tika.detect.Detector;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaCoreProperties;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.mime.MimeTypes;
+import org.apache.tika.parser.AutoDetectParser;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
/**
* 三级等保 文件上传 相关
@@ -23,6 +35,28 @@ public class SecurityFileService {
@Resource
private Level3ProtectConfigService level3ProtectConfigService;
+ // 定义白名单MIME类型
+ private static final List ALLOWED_MIME_TYPES = Arrays.asList(
+ "application/json",
+ "application/zip",
+ "application/x-7z-compressed",
+ "application/pdf",
+ "application/vnd.ms-excel",
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ "application/vnd.ms-powerpoint",
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+ "application/msword",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ "application/vnd.ms-works",
+ "text/csv",
+ "audio/*",
+ "video/*",
+ // 图片类型 svg有安全隐患,所以不使用"image/*"
+ "image/jpeg",
+ "image/png",
+ "image/gif",
+ "image/bmp"
+ );
/**
* 检测文件安全类型
@@ -38,15 +72,50 @@ public class SecurityFileService {
}
// 文件类型安全检测
- if (!level3ProtectConfigService.isFileDetectFlag()) {
- return ResponseDTO.ok();
+ if (level3ProtectConfigService.isFileDetectFlag()) {
+ String fileType = getFileMimeType(file);
+ if(ALLOWED_MIME_TYPES.stream()
+ .noneMatch(allowedType -> matchesMimeType(fileType, allowedType))){
+ return ResponseDTO.userErrorParam("禁止上传此文件类型");
+ }
}
- // 检测文件类型
- // .....
-
return ResponseDTO.ok();
}
+ /**
+ * 获取文件的 MIME 类型
+ *
+ * @param file 要检查的文件
+ * @return 文件的 MIME 类型
+ *
+ */
+ public static String getFileMimeType(MultipartFile file) {
+ try {
+ TikaConfig tika = new TikaConfig();
+ Metadata metadata = new Metadata();
+ metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, file.getOriginalFilename());
+ TikaInputStream stream = TikaInputStream.get(file.getInputStream());
+ MediaType mimetype = tika.getDetector().detect(stream, metadata);
+ return mimetype.toString();
+ } catch (IOException | TikaException e) {
+ return MimeTypes.OCTET_STREAM;
+ }
+ }
+
+ /**
+ * 检查文件的 MIME 类型是否与指定的MIME 类型匹配(支持通配符)
+ *
+ * @param fileType 文件的 MIME 类型
+ * @param mimetype MIME 类型(支持通配符)
+ * @return 是否匹配
+ */
+ private static boolean matchesMimeType(String fileType, String mimetype) {
+ if (mimetype.endsWith("/*")) {
+ String prefix = mimetype.substring(0, mimetype.length() - 1);
+ return fileType.startsWith(prefix);
+ } else {
+ return fileType.equalsIgnoreCase(mimetype);
+ }
+ }
}
-;
\ No newline at end of file