From 4470052c3b6bdeb18e45987f8aa293d1e93d0552 Mon Sep 17 00:00:00 2001
From: Ludc <2870569285@qq.com>
Date: 星期二, 18 十一月 2025 11:59:12 +0800
Subject: [PATCH] 所有文件上传接口增加文件安全校验逻辑。
---
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/CodeClassifyController.java | 14 +
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/controller/FileController.java | 19 +
Source/UBCS/ubcs-service/ubcs-system/src/main/java/com/vci/ubcs/system/controller/RegionController.java | 13 +
Source/UBCS/ubcs-service/ubcs-user/src/main/java/com/vci/ubcs/system/user/controller/UserController.java | 19 +
Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/endpoint/OssEndpoint.java | 50 +--
Source/UBCS/ubcs-common/src/main/java/com/vci/ubcs/common/validator/ComprehensiveFileValidator.java | 477 +++++++++++++++++++++++++++++++++++++++
Source/UBCS/ubcs-gateway/src/main/java/com/vci/ubcs/gateway/filter/EssentialSecurityFilter.java | 42 +++
Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/controller/FlowManagerController.java | 19 +
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/MdmEngineController.java | 40 +++
Source/UBCS/ubcs-service/ubcs-deploy/src/main/java/com/vci/ubcs/deploy/controller/DeployAppsController.java | 13 +
10 files changed, 663 insertions(+), 43 deletions(-)
diff --git a/Source/UBCS/ubcs-common/src/main/java/com/vci/ubcs/common/validator/ComprehensiveFileValidator.java b/Source/UBCS/ubcs-common/src/main/java/com/vci/ubcs/common/validator/ComprehensiveFileValidator.java
new file mode 100644
index 0000000..96b19cc
--- /dev/null
+++ b/Source/UBCS/ubcs-common/src/main/java/com/vci/ubcs/common/validator/ComprehensiveFileValidator.java
@@ -0,0 +1,477 @@
+package com.vci.ubcs.common.validator;
+
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 鏂囦欢瀹夊叏楠岃瘉鍣�
+ */
+@Component
+@Slf4j
+public class ComprehensiveFileValidator {
+
+ /**
+ * 鏂囦欢鐧藉悕鍗�
+ */
+ @Value("${app.upload.security.allowed-extensions:jpg,jpeg,png,pdf}")
+ private String allowedExtensionsConfig;
+
+ /**
+ * 澶氶噸鎵╁睍鍚嶆枃浠剁姝�
+ */
+ @Value("${app.upload.security.prevent-multiple-extensions:true}")
+ private boolean preventMultipleExtensions;
+
+ /**
+ * 闄愬埗鐨勫嵄闄╂枃浠剁被鍨�
+ */
+ @Value("${app.upload.security.dangerous-primary-extensions:jsp,jspx,php,asp,aspx,war,exe,sh,bat}")
+ private String dangerousExtensionsConfig;
+
+ /**
+ * 鏂囦欢鍐呭绫诲瀷鏄惁鍖归厤鏍¢獙
+ */
+ @Value("${app.upload.security.validate-content-type:true}")
+ private boolean validateContentType;
+
+ /**
+ * 鏂囦欢澶撮獙璇�
+ */
+ @Value("${app.upload.security.validate-file-header:true}")
+ private boolean validateFileHeader;
+
+ /**
+ * 涓ユ牸妯″紡
+ */
+ @Value("${app.upload.security.strict-mode:false}")
+ private boolean strictMode;
+
+ /**
+ * 鍏佽涓婁紶鐨勫悗缂�
+ */
+ private Set<String> allowedExtensions;
+
+ /**
+ * 鍗遍櫓鐨勬枃浠跺悗缂�
+ */
+ private Set<String> dangerousPrimaryExtensions;
+
+ @PostConstruct
+ public void init() {
+ // 瑙f瀽閫楀彿鍒嗛殧鐨勯厤缃�
+ this.allowedExtensions = parseCommaSeparatedConfig(allowedExtensionsConfig);
+ this.dangerousPrimaryExtensions = parseCommaSeparatedConfig(dangerousExtensionsConfig);
+
+ log.info("鏂囦欢涓婁紶楠岃瘉鍣ㄥ垵濮嬪寲瀹屾垚");
+ log.info("鍏佽鐨勬墿灞曞悕: {}", allowedExtensions);
+ log.info("鍗遍櫓鎵╁睍鍚�: {}", dangerousPrimaryExtensions);
+ }
+
+ private Set<String> parseCommaSeparatedConfig(String config) {
+ if (config == null || config.trim().isEmpty()) {
+ return new HashSet<>();
+ }
+ return Arrays.stream(config.split(","))
+ .map(String::trim)
+ .map(String::toLowerCase)
+ .collect(Collectors.toSet());
+ }
+
+ /**
+ * 楠岃瘉鍗曚釜鏂囦欢
+ */
+ public UploadValidationResult validateFile(MultipartFile file) {
+ UploadValidationResult result = new UploadValidationResult();
+
+ try {
+ // 鍩虹妫�鏌�
+ if (!basicValidation(file, result)) {
+ return result;
+ }
+
+ String filename = file.getOriginalFilename();
+
+ // 鏂囦欢鍚嶅畨鍏ㄩ獙璇�
+ if (!filenameSecurityValidation(filename, result)) {
+ return result;
+ }
+
+ // 鍐呭瀹夊叏楠岃瘉
+ if (!contentSecurityValidation(file, result)) {
+ return result;
+ }
+
+ result.setValid(true);
+ result.setMessage("鏂囦欢楠岃瘉閫氳繃");
+
+ } catch (Exception e) {
+ log.error("鏂囦欢楠岃瘉寮傚父", e);
+ result.setValid(false);
+ result.setMessage("楠岃瘉杩囩▼鍙戠敓寮傚父");
+ }
+
+ return result;
+ }
+
+ /**
+ * 楠岃瘉澶氫釜鏂囦欢
+ * @param files 鏂囦欢鍒楄〃
+ * @return 澶氫釜鏂囦欢鐨勯獙璇佺粨鏋�
+ */
+ public MultiUploadValidationResult validateFiles(List<MultipartFile> files) {
+ return validateFiles(files, false);
+ }
+
+ /**
+ * 楠岃瘉澶氫釜鏂囦欢
+ * @param files 鏂囦欢鍒楄〃
+ * @param stopOnFirstError 閬囧埌绗竴涓敊璇槸鍚﹀仠姝㈤獙璇�
+ * @return 澶氫釜鏂囦欢鐨勯獙璇佺粨鏋�
+ */
+ public MultiUploadValidationResult validateFiles(List<MultipartFile> files, boolean stopOnFirstError) {
+ MultiUploadValidationResult result = new MultiUploadValidationResult();
+
+ if (files == null || files.isEmpty()) {
+ result.setValid(false);
+ result.setMessage("鏂囦欢鍒楄〃涓虹┖");
+ return result;
+ }
+
+ List<FileValidationDetail> details = new ArrayList<>();
+ boolean allValid = true;
+
+ for (int i = 0; i < files.size(); i++) {
+ MultipartFile file = files.get(i);
+ FileValidationDetail detail = new FileValidationDetail();
+ detail.setFileName(file.getOriginalFilename());
+ detail.setFileIndex(i);
+ detail.setFileSize(file.getSize());
+
+ // 楠岃瘉鍗曚釜鏂囦欢
+ UploadValidationResult singleResult = validateFile(file);
+ detail.setValid(singleResult.isValid());
+ detail.setMessage(singleResult.getMessage());
+ detail.setDetectedType(singleResult.getDetectedType());
+
+ details.add(detail);
+
+ if (!singleResult.isValid()) {
+ allValid = false;
+ if (stopOnFirstError) {
+ // 閬囧埌閿欒涓旇缃负蹇�熷け璐ワ紝绔嬪嵆杩斿洖
+ result.setValid(false);
+ result.setMessage("绗�" + (i + 1) + "涓枃浠堕獙璇佸け璐�: " + file.getOriginalFilename());
+ result.setDetails(details);
+ result.setFailedIndex(i);
+ return result;
+ }
+ }
+ }
+
+ result.setValid(allValid);
+ result.setMessage(allValid ? "鎵�鏈夋枃浠堕獙璇侀�氳繃" : "閮ㄥ垎鏂囦欢楠岃瘉澶辫触");
+ result.setDetails(details);
+ result.setTotalFiles(files.size());
+ result.setValidFiles((int) details.stream().filter(FileValidationDetail::isValid).count());
+ result.setInvalidFiles((int) details.stream().filter(d -> !d.isValid()).count());
+
+ return result;
+ }
+
+ /**
+ * 楠岃瘉澶氫釜鏂囦欢锛堟暟缁勭増鏈級
+ */
+ public MultiUploadValidationResult validateFiles(MultipartFile[] files) {
+ return validateFiles(Arrays.asList(files));
+ }
+
+ /**
+ * 楠岃瘉澶氫釜鏂囦欢锛堟暟缁勭増鏈紝鍙缃槸鍚﹀揩閫熷け璐ワ級
+ */
+ public MultiUploadValidationResult validateFiles(MultipartFile[] files, boolean stopOnFirstError) {
+ return validateFiles(Arrays.asList(files), stopOnFirstError);
+ }
+
+ /**
+ * 鎵归噺楠岃瘉鏂囦欢骞惰繑鍥炴湁鏁堢殑鏂囦欢鍒楄〃
+ */
+ public List<MultipartFile> getValidFiles(List<MultipartFile> files) {
+ MultiUploadValidationResult result = validateFiles(files);
+ List<MultipartFile> validFiles = new ArrayList<>();
+
+ for (int i = 0; i < files.size(); i++) {
+ if (result.getDetails().get(i).isValid()) {
+ validFiles.add(files.get(i));
+ }
+ }
+
+ return validFiles;
+ }
+
+ /**
+ * 妫�鏌ユ槸鍚︽墍鏈夋枃浠堕兘鏈夋晥
+ */
+ public boolean areAllFilesValid(List<MultipartFile> files) {
+ MultiUploadValidationResult result = validateFiles(files);
+ return result.isValid();
+ }
+
+ // 鍘熸湁鐨勭鏈夋柟娉曚繚鎸佷笉鍙�
+ private boolean basicValidation(MultipartFile file, UploadValidationResult result) {
+ if (file == null || file.isEmpty()) {
+ result.setMessage("鏂囦欢涓虹┖");
+ return false;
+ }
+
+ String filename = file.getOriginalFilename();
+ if (filename == null || filename.trim().isEmpty()) {
+ result.setMessage("鏂囦欢鍚嶄负绌�");
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean filenameSecurityValidation(String filename, UploadValidationResult result) {
+ // 璺緞閬嶅巻妫�鏌�
+ if (filename.contains("..") || filename.contains("/") || filename.contains("\\")) {
+ result.setMessage("鏂囦欢鍚嶅寘鍚嵄闄╁瓧绗�");
+ return false;
+ }
+
+ // 鎵╁睍鍚嶆鏌�
+ String finalExtension = getFinalExtension(filename);
+ if (finalExtension.isEmpty() || !allowedExtensions.contains(finalExtension.toLowerCase())) {
+ result.setMessage("涓嶆敮鎸佺殑鏂囦欢绫诲瀷: " + finalExtension);
+ return false;
+ }
+
+ // 澶氶噸鎵╁睍鍚嶆鏌�
+ if (preventMultipleExtensions && hasMultipleExtensions(filename)) {
+ if (strictMode) {
+ // 涓ユ牸妯″紡锛氭嫤鎴墍鏈夊閲嶆墿灞曞悕
+ result.setMessage("澶氶噸鎵╁睍鍚嶆枃浠惰绂佹");
+ return false;
+ } else {
+ // 鏅�氭ā寮忥細鍙嫤鎴寘鍚嵄闄╂墿灞曞悕鐨勫閲嶆墿灞曞悕
+ if (containsDangerousExtension(filename)) {
+ result.setMessage("妫�娴嬪埌浼Webshell鏂囦欢: " + filename);
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private boolean contentSecurityValidation(MultipartFile file, UploadValidationResult result) {
+ // 鍐呭绫诲瀷楠岃瘉
+ if (validateContentType && !validateContentType(file)) {
+ result.setMessage("鏂囦欢鍐呭绫诲瀷涓嶅尮閰�");
+ return false;
+ }
+
+ // 鏂囦欢澶撮獙璇�
+ if (validateFileHeader && !validateFileHeader(file)) {
+ result.setMessage("鏂囦欢澶撮獙璇佸け璐�");
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean hasMultipleExtensions(String filename) {
+ String name = getFileNameWithoutPath(filename);
+ return name.chars().filter(ch -> ch == '.').count() > 1;
+ }
+
+ private boolean containsDangerousExtension(String filename) {
+ String name = getFileNameWithoutPath(filename);
+ String[] parts = name.split("\\.");
+
+ // 妫�鏌ラ櫎鏈�鍚庝竴涓墿灞曞悕涔嬪鐨勬墍鏈夐儴鍒�
+ for (int i = 0; i < parts.length - 1; i++) {
+ String part = parts[i].toLowerCase();
+ if (dangerousPrimaryExtensions.contains(part)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean validateContentType(MultipartFile file) {
+ try {
+ String declaredType = file.getContentType();
+ if (declaredType == null) {
+ return true; // 娌℃湁澹版槑绫诲瀷锛屾斁杩�
+ }
+
+ // 绠�鍗曠殑绫诲瀷鍖归厤妫�鏌�
+ String finalExtension = getFinalExtension(file.getOriginalFilename()).toLowerCase();
+ return isContentTypeConsistent(declaredType, finalExtension);
+ } catch (Exception e) {
+ log.error("鍐呭绫诲瀷楠岃瘉澶辫触", e);
+ return false;
+ }
+ }
+
+ /**
+ * 楠岃瘉鏂囦欢鐨勫唴瀹圭被鍨嬶紙Content-Type锛夋槸鍚︿笌鏂囦欢鎵╁睍鍚嶄竴鑷�
+ * @param contentType
+ * @param extension
+ * @return
+ */
+ private boolean isContentTypeConsistent(String contentType, String extension) {
+ // 鎵╁睍鏇村叏闈㈢殑绫诲瀷鏄犲皠
+ Map<String, String> expectedTypes = new HashMap<>();
+
+ // 鍥剧墖绫诲瀷
+ expectedTypes.put("jpg", "image/jpeg");
+ expectedTypes.put("jpeg", "image/jpeg");
+ expectedTypes.put("png", "image/png");
+ expectedTypes.put("gif", "image/gif");
+ expectedTypes.put("bmp", "image/bmp");
+ expectedTypes.put("webp", "image/webp");
+ expectedTypes.put("svg", "image/svg+xml");
+
+ // 鏂囨。绫诲瀷
+ expectedTypes.put("pdf", "application/pdf");
+ expectedTypes.put("doc", "application/msword");
+ expectedTypes.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
+ expectedTypes.put("xls", "application/vnd.ms-excel");
+ expectedTypes.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+ expectedTypes.put("ppt", "application/vnd.ms-powerpoint");
+ expectedTypes.put("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
+ expectedTypes.put("txt", "text/plain");
+
+ // 鍘嬬缉鏂囦欢
+ expectedTypes.put("zip", "application/zip");
+ expectedTypes.put("rar", "application/x-rar-compressed");
+ expectedTypes.put("7z", "application/x-7z-compressed");
+
+ String expectedType = expectedTypes.get(extension);
+ return expectedType == null || expectedType.equalsIgnoreCase(contentType);
+ }
+
+ private boolean validateFileHeader(MultipartFile file) {
+ try {
+ byte[] header = new byte[8];
+ int bytesRead = file.getInputStream().read(header);
+
+ if (bytesRead < 4) {
+ return false;
+ }
+
+ String finalExtension = getFinalExtension(file.getOriginalFilename()).toLowerCase();
+
+ // 鍩虹鐨勬枃浠跺ご楠岃瘉
+ switch (finalExtension) {
+ case "jpg":
+ case "jpeg":
+ return isJpeg(header);
+ case "png":
+ return isPng(header);
+ case "pdf":
+ return isPdf(header);
+ case "gif":
+ return isGif(header);
+ default:
+ return true; // 鍏朵粬绫诲瀷涓嶉獙璇佹枃浠跺ご
+ }
+ } catch (IOException e) {
+ log.error("鏂囦欢澶撮獙璇佸け璐�", e);
+ return false;
+ }
+ }
+
+ /**
+ * 鏂囦欢澶撮獙璇佹柟娉�
+ * @param header
+ * @return
+ */
+ private boolean isJpeg(byte[] header) {
+ return (header[0] & 0xFF) == 0xFF && (header[1] & 0xFF) == 0xD8;
+ }
+
+ private boolean isPng(byte[] header) {
+ return header[0] == (byte) 0x89 && header[1] == 0x50 &&
+ header[2] == 0x4E && header[3] == 0x47;
+ }
+
+ private boolean isPdf(byte[] header) {
+ return header[0] == 0x25 && header[1] == 0x50 &&
+ header[2] == 0x44 && header[3] == 0x46;
+ }
+
+ private boolean isGif(byte[] header) {
+ return header[0] == 'G' && header[1] == 'I' &&
+ header[2] == 'F' && header[3] == '8';
+ }
+
+ // 杈呭姪鏂规硶
+ private String getFinalExtension(String filename) {
+ if (filename == null || !filename.contains(".")) return "";
+ String[] parts = filename.split("\\.");
+ return parts[parts.length - 1];
+ }
+
+ private String getFileNameWithoutPath(String filename) {
+ if (filename == null) return "";
+ filename = filename.replace('\\', '/');
+ int lastSlash = filename.lastIndexOf('/');
+ return lastSlash >= 0 ? filename.substring(lastSlash + 1) : filename;
+ }
+
+ @Data
+ public static class UploadValidationResult {
+ private boolean valid;
+ private String message;
+ private String detectedType;
+
+ public UploadValidationResult() {
+ this.valid = false;
+ this.message = "";
+ }
+ }
+
+ /**
+ * 澶氭枃浠堕獙璇佺粨鏋�
+ */
+ @Data
+ public static class MultiUploadValidationResult {
+ private boolean valid;
+ private String message;
+ private int totalFiles;
+ private int validFiles;
+ private int invalidFiles;
+ private int failedIndex = -1; // 绗竴涓け璐ョ殑鏂囦欢绱㈠紩
+ private List<FileValidationDetail> details;
+
+ public MultiUploadValidationResult() {
+ this.valid = false;
+ this.message = "";
+ this.details = new ArrayList<>();
+ }
+ }
+
+ /**
+ * 鍗曚釜鏂囦欢楠岃瘉璇︽儏
+ */
+ @Data
+ public static class FileValidationDetail {
+ private String fileName;
+ private int fileIndex;
+ private long fileSize;
+ private boolean valid;
+ private String message;
+ private String detectedType;
+ }
+}
diff --git a/Source/UBCS/ubcs-gateway/src/main/java/com/vci/ubcs/gateway/filter/EssentialSecurityFilter.java b/Source/UBCS/ubcs-gateway/src/main/java/com/vci/ubcs/gateway/filter/EssentialSecurityFilter.java
new file mode 100644
index 0000000..9813539
--- /dev/null
+++ b/Source/UBCS/ubcs-gateway/src/main/java/com/vci/ubcs/gateway/filter/EssentialSecurityFilter.java
@@ -0,0 +1,42 @@
+package com.vci.ubcs.gateway.filter;
+
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+/**
+ * 缃戝叧杩囨护鍣紝鎷︽埅鏄庣‘鐨勬敾鍑荤壒寰�
+ */
+public class EssentialSecurityFilter implements GlobalFilter {
+
+ @Override
+ public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ ServerHttpRequest request = exchange.getRequest();
+ String path = request.getPath().value();
+
+ // 鍙嫤鎴渶鍗遍櫓鐨勮姹�
+ if (isDefinitelyDangerous(path)) {
+ return blockRequest(exchange, "鍗遍櫓璇锋眰琚嫤鎴紒");
+ }
+
+ return chain.filter(exchange);
+ }
+
+ private boolean isDefinitelyDangerous(String path) {
+ // 鍙嫤鎴槑纭殑鏀诲嚮鐗瑰緛
+ return path.contains("../") ||
+ path.contains("/WEB-INF/") ||
+ path.matches(".*\\.(jsp|war|sh|bat|exe)$") ||
+ path.contains("cmd.exe") ||
+ path.contains("/bin/");
+ }
+
+ private Mono<Void> blockRequest(ServerWebExchange exchange, String message) {
+ exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
+ return exchange.getResponse().setComplete();
+ }
+
+}
diff --git a/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/controller/FlowManagerController.java b/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/controller/FlowManagerController.java
index 6c41ebc..c46518a 100644
--- a/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/controller/FlowManagerController.java
+++ b/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/controller/FlowManagerController.java
@@ -18,6 +18,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.vci.ubcs.common.validator.ComprehensiveFileValidator;
import com.vci.ubcs.flow.engine.entity.FlowProcess;
import com.vci.ubcs.flow.engine.service.FlowEngineService;
import io.swagger.annotations.Api;
@@ -31,6 +32,7 @@
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import com.vci.ubcs.flow.engine.constant.FlowEngineConstant;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@@ -47,10 +49,15 @@
@RequestMapping("manager")
@AllArgsConstructor
@Api(value = "娴佺▼绠$悊鎺ュ彛", tags = "娴佺▼绠$悊鎺ュ彛")
-//@PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
public class FlowManagerController {
private final FlowEngineService flowEngineService;
+
+ /**
+ * 鏂囦欢瀹夊叏妫�鏌�
+ */
+ @Autowired
+ private ComprehensiveFileValidator fileValidator;
/**
* 鍒嗛〉
@@ -98,6 +105,11 @@
@ApiOperationSupport(order = 4)
@ApiOperation(value = "涓婁紶閮ㄧ讲娴佺▼鏂囦欢", notes = "浼犲叆鏂囦欢")
public R checkUpload(@RequestParam MultipartFile file) {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.UploadValidationResult result = fileValidator.validateFile(file);
+ if (!result.isValid()) {
+ return R.fail(result.getMessage());
+ }
boolean temp = Objects.requireNonNull(file.getOriginalFilename()).endsWith(FlowEngineConstant.SUFFIX);
return R.data(Kv.create().set("name", file.getOriginalFilename()).set("success", temp));
}
@@ -114,6 +126,11 @@
public R deployUpload(@RequestParam List<MultipartFile> files,
@RequestParam String category,
@RequestParam(required = false, defaultValue = "") String tenantIds) {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.MultiUploadValidationResult result = fileValidator.validateFiles(files,true);
+ if (!result.isValid()) {
+ return R.fail(result.getMessage());
+ }
return R.status(flowEngineService.deployUpload(files, category, Func.toStrList(tenantIds)));
}
diff --git a/Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/controller/FileController.java b/Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/controller/FileController.java
index 626effe..42a7ba4 100644
--- a/Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/controller/FileController.java
+++ b/Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/controller/FileController.java
@@ -1,8 +1,8 @@
package com.vci.ubcs.resource.controller;
-import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.vci.ubcs.common.validator.ComprehensiveFileValidator;
import com.vci.ubcs.resource.dto.FileObjectDTO;
import com.vci.ubcs.resource.dto.FileReleaseDTO;
import com.vci.ubcs.resource.dto.FileShareDTO;
@@ -10,14 +10,11 @@
import com.vci.ubcs.resource.service.IFileService;
import com.vci.ubcs.resource.utils.FileDownloadUtil;
import com.vci.ubcs.resource.vo.FileObjectVO;
-import com.vci.ubcs.starter.exception.VciBaseException;
import com.vci.ubcs.starter.web.util.ControllerUtil;
import com.vci.ubcs.starter.web.util.LangBaseUtil;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
-import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.mp.support.Query;
-import org.springblade.core.oss.MinioTemplate;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
@@ -45,6 +42,12 @@
*/
@Autowired
private IFileService fileService;
+
+ /**
+ * 鏂囦欢瀹夊叏妫�鏌�
+ */
+ @Autowired
+ private ComprehensiveFileValidator fileValidator;
/**
* 鏍规嵁鏂囦欢涓婚敭涓嬭浇鏂囦欢
@@ -82,7 +85,7 @@
if(StringUtil.isBlank(msg)){
msg = "鏈煡閿欒";
}
- log.debug(msg);
+ log.error(msg);
return R.fail(msg);
}
return R.success("鍒犻櫎鎴愬姛");
@@ -97,6 +100,12 @@
@PostMapping("/uploadFile")
public R<FileObjectVO> uploadFile(MultipartFile file, FileObjectDTO fileObjectDTO){
if (file != null ) {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.UploadValidationResult result = fileValidator.validateFile(file);
+ if (!result.isValid()) {
+ return R.fail(result.getMessage());
+ }
+ //涓婁紶鏂囦欢
return fileService.uploadFile(file, fileObjectDTO);
} else {
return R.fail("鏃犱笂浼犵殑鏂囦欢");
diff --git a/Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/endpoint/OssEndpoint.java b/Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/endpoint/OssEndpoint.java
index 1bdefc5..909f7f1 100644
--- a/Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/endpoint/OssEndpoint.java
+++ b/Source/UBCS/ubcs-ops/ubcs-resource/src/main/java/com/vci/ubcs/resource/endpoint/OssEndpoint.java
@@ -17,6 +17,7 @@
package com.vci.ubcs.resource.endpoint;
import com.vci.ubcs.resource.entity.Attach;
+import com.vci.ubcs.common.validator.ComprehensiveFileValidator;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
@@ -31,8 +32,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
-
-import javax.servlet.http.HttpServletResponse;
/**
* 瀵硅薄瀛樺偍绔偣
@@ -59,6 +58,11 @@
*/
private final IAttachService attachService;
+ /**
+ * 鏂囦欢瀹夊叏妫�鏌�
+ */
+ @Autowired
+ private ComprehensiveFileValidator fileValidator;
/**
* 鍒涘缓瀛樺偍妗�
@@ -150,6 +154,11 @@
@SneakyThrows
@PostMapping("/put-file")
public R<BladeFile> putFile(@RequestParam MultipartFile file) {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.UploadValidationResult result = fileValidator.validateFile(file);
+ if (!result.isValid()) {
+ return R.fail(result.getMessage());
+ }
BladeFile bladeFile = ossBuilder.template().putFile(file.getOriginalFilename(), file.getInputStream());
return R.data(bladeFile);
}
@@ -164,41 +173,14 @@
@SneakyThrows
@PostMapping("/put-file-by-name")
public R<BladeFile> putFile(@RequestParam String fileName, @RequestParam MultipartFile file) {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.UploadValidationResult result = fileValidator.validateFile(file);
+ if (!result.isValid()) {
+ return R.fail(result.getMessage());
+ }
BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream());
return R.data(bladeFile);
}
-
-// /**
-// * 涓婁紶鏂囦欢骞朵繚瀛樿嚦闄勪欢琛�
-// *
-// * @param file 鏂囦欢
-// * @return ObjectStat
-// */
-// @SneakyThrows
-// @PostMapping("/put-file-attach")
-// public R<BladeFile> putFileAttach(@RequestParam MultipartFile file) {
-// String fileName = file.getOriginalFilename();
-// BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream());
-// Long attachId = buildAttach(fileName, file.getSize(), bladeFile);
-// bladeFile.setAttachId(attachId);
-// return R.data(bladeFile);
-// }
-
-// /**
-// * 涓婁紶鏂囦欢骞朵繚瀛樿嚦闄勪欢琛�
-// *
-// * @param fileName 瀛樺偍妗跺璞″悕绉�
-// * @param file 鏂囦欢
-// * @return ObjectStat
-// */
-// @SneakyThrows
-// @PostMapping("/put-file-attach-by-name")
-// public R<BladeFile> putFileAttach(@RequestParam String fileName, @RequestParam MultipartFile file) {
-// BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream());
-// Long attachId = buildAttach(fileName, file.getSize(), bladeFile);
-// bladeFile.setAttachId(attachId);
-// return R.data(bladeFile);
-// }
/**
* 鏋勫缓闄勪欢琛�
diff --git a/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/CodeClassifyController.java b/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/CodeClassifyController.java
index df82de1..06ddc94 100644
--- a/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/CodeClassifyController.java
+++ b/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/CodeClassifyController.java
@@ -25,6 +25,7 @@
import com.vci.ubcs.code.vo.pagemodel.CodeClassifyVO;
import com.vci.ubcs.code.vo.pagemodel.CodeImProtRusultVO;
import com.vci.ubcs.code.wrapper.CodeClassifyWrapper;
+import com.vci.ubcs.common.validator.ComprehensiveFileValidator;
import com.vci.ubcs.omd.vo.BtmTypeAttributeVO;
import com.vci.ubcs.starter.revision.model.TreeQueryObject;
import com.vci.ubcs.starter.util.LocalFileUtil;
@@ -47,6 +48,7 @@
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
@@ -77,6 +79,12 @@
private final ICodeClassifyService codeClassifyService;
CodeClassifyMapper codeClassifyMapper;
+
+ /**
+ * 鏂囦欢瀹夊叏妫�鏌�
+ */
+ @Autowired
+ private ComprehensiveFileValidator fileValidator;
/**
* 涓婚搴撳畾涔夎〃 璇︽儏
@@ -277,6 +285,12 @@
*/
@PostMapping("/importClassify")
public R importClassify(MultipartFile file) {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.UploadValidationResult result = fileValidator.validateFile(file);
+ if (!result.isValid()) {
+ return R.fail(result.getMessage());
+ }
+
String excelFileName = LocalFileUtil.getDefaultTempFolder() + File.separator + LocalFileUtil.getFileNameForIE(file.getOriginalFilename());
File file1 = new File(excelFileName);
try {
diff --git a/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/MdmEngineController.java b/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/MdmEngineController.java
index 7e3cf21..623570c 100644
--- a/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/MdmEngineController.java
+++ b/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/MdmEngineController.java
@@ -10,6 +10,7 @@
import com.vci.ubcs.code.service.MdmEngineService;
import com.vci.ubcs.code.service.MdmIOService;
import com.vci.ubcs.code.vo.pagemodel.*;
+import com.vci.ubcs.common.validator.ComprehensiveFileValidator;
import com.vci.ubcs.flow.core.dto.FlowStatusDTO;
import com.vci.ubcs.starter.annotation.VciBusinessLog;
import com.vci.ubcs.starter.revision.model.BaseModel;
@@ -43,21 +44,31 @@
* 鏃ュ織
*/
private Logger logger = LoggerFactory.getLogger(getClass());
+
/**
* 涓绘暟鎹紩鎿庢湇鍔�
*/
@Autowired
private MdmEngineService engineService;
+
/**
* 涓绘暟鎹鍏ュ鍑烘湇鍔�
*/
@Autowired
private MdmIOService mdmIOService;
+
/**
* 鏃ュ織淇濆瓨宸ュ叿绫�
*/
@Autowired
private SaveLogUtil saveLogUtil;
+
+ /**
+ * 鏂囦欢瀹夊叏妫�鏌�
+ */
+ @Autowired
+ private ComprehensiveFileValidator fileValidator;
+
/**
* 涓嬭浇鎵归噺鐢宠鐨勫鍏ユā鏉�
@@ -112,6 +123,12 @@
@VciBusinessLog(operateName = "瀵煎叆鎵归噺缂栬緫鏁版嵁")
@PostMapping("/batchImportEdit")
public R batchImportEdit(String codeClassifyOid, String classifyAttr,MultipartFile file,HttpServletResponse response) throws Throwable {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.UploadValidationResult validationResult = fileValidator.validateFile(file);
+ if (!validationResult.isValid()) {
+ return R.fail(validationResult.getMessage());
+ }
+
String excelFileName = LocalFileUtil.getDefaultTempFolder() + File.separator + file.getOriginalFilename();
File file1 = new File(excelFileName);
try {
@@ -218,6 +235,12 @@
@VciBusinessLog(operateName = "鎵归噺鐢宠缂栫爜鐨勪俊鎭�")
@PostMapping("/batchImportCode")
public R batchImportCode(String secDTOList, String codeClassifyOid, MultipartFile file, HttpServletResponse response) throws Throwable {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.UploadValidationResult validationResult = fileValidator.validateFile(file);
+ if (!validationResult.isValid()) {
+ return R.fail(validationResult.getMessage());
+ }
+
CodeOrderDTO orderDTO = new CodeOrderDTO();
orderDTO.setCodeClassifyOid(codeClassifyOid);
if(StringUtils.isNotBlank(secDTOList)){
@@ -269,6 +292,12 @@
@VciBusinessLog(operateName = "瀵煎叆缂栫爜鐨勫巻鍙叉暟鎹�")
@PostMapping("/batchImportHistoryData")
public R batchImportHistoryData(String codeClassifyOid, String classifyAttr,MultipartFile file,HttpServletResponse response) throws Throwable {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.UploadValidationResult validationResult = fileValidator.validateFile(file);
+ if (!validationResult.isValid()) {
+ return R.fail(validationResult.getMessage());
+ }
+
String excelFileName = LocalFileUtil.getDefaultTempFolder() + File.separator + file.getOriginalFilename();
File file1 = new File(excelFileName);
try {
@@ -312,6 +341,12 @@
@VciBusinessLog(operateName = "鎵归噺鐢宠缂栫爜鐨勪俊鎭�")
@PostMapping("/batchTopImportCode")
public R batchTopImportCode(String codeClassifyOid, String classifyAttr,MultipartFile file,HttpServletResponse response) throws Throwable {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.UploadValidationResult result = fileValidator.validateFile(file);
+ if (!result.isValid()) {
+ return R.fail(result.getMessage());
+ }
+
String excelFileName = LocalFileUtil.getDefaultTempFolder() + File.separator + file.getOriginalFilename();
File file1 = new File(excelFileName);
try {
@@ -867,6 +902,11 @@
*/
@PostMapping("/importGroupCode")
public R importGroupCode(String codeClassifyOid,MultipartFile file,HttpServletResponse response){
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.UploadValidationResult result = fileValidator.validateFile(file);
+ if (!result.isValid()) {
+ return R.fail(result.getMessage());
+ }
String excelFileName = LocalFileUtil.getDefaultTempFolder() + File.separator + file.getOriginalFilename();
File file1 = new File(excelFileName);
diff --git a/Source/UBCS/ubcs-service/ubcs-deploy/src/main/java/com/vci/ubcs/deploy/controller/DeployAppsController.java b/Source/UBCS/ubcs-service/ubcs-deploy/src/main/java/com/vci/ubcs/deploy/controller/DeployAppsController.java
index 5c13be2..05dd46f 100644
--- a/Source/UBCS/ubcs-service/ubcs-deploy/src/main/java/com/vci/ubcs/deploy/controller/DeployAppsController.java
+++ b/Source/UBCS/ubcs-service/ubcs-deploy/src/main/java/com/vci/ubcs/deploy/controller/DeployAppsController.java
@@ -1,6 +1,7 @@
package com.vci.ubcs.deploy.controller;
import com.alibaba.nacos.shaded.com.google.protobuf.ServiceException;
+import com.vci.ubcs.common.validator.ComprehensiveFileValidator;
import com.vci.ubcs.deploy.entity.DeployApps;
import com.vci.ubcs.deploy.service.IDeployAppsService;
import com.vci.ubcs.deploy.vo.DeployAppsVO;
@@ -10,6 +11,7 @@
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;
@@ -32,6 +34,12 @@
public class DeployAppsController {
private final IDeployAppsService deployAppsService;
+
+ /**
+ * 鏂囦欢瀹夊叏妫�鏌�
+ */
+ @Autowired
+ private ComprehensiveFileValidator fileValidator;
/**
* 鑾峰彇鏈嶅姟杩愯鍒楄〃
@@ -86,6 +94,11 @@
*/
@PostMapping("/importUpdateServiceJar")
public R importClassify(@RequestParam("files") MultipartFile[] files,@RequestParam String serverName) throws ServiceException {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.MultiUploadValidationResult quickResult = fileValidator.validateFiles(files, true);
+ if (!quickResult.isValid()) {
+ return R.fail(quickResult.getMessage());
+ }
if(Func.isBlank(serverName)){
return R.fail("Mandatory parameter service name not found!");
}
diff --git a/Source/UBCS/ubcs-service/ubcs-system/src/main/java/com/vci/ubcs/system/controller/RegionController.java b/Source/UBCS/ubcs-service/ubcs-system/src/main/java/com/vci/ubcs/system/controller/RegionController.java
index 80044f3..61186aa 100644
--- a/Source/UBCS/ubcs-service/ubcs-system/src/main/java/com/vci/ubcs/system/controller/RegionController.java
+++ b/Source/UBCS/ubcs-service/ubcs-system/src/main/java/com/vci/ubcs/system/controller/RegionController.java
@@ -20,6 +20,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.vci.ubcs.common.validator.ComprehensiveFileValidator;
import com.vci.ubcs.system.entity.Region;
import com.vci.ubcs.system.excel.RegionExcel;
import com.vci.ubcs.system.excel.RegionImporter;
@@ -35,6 +36,7 @@
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;
@@ -58,6 +60,12 @@
public class RegionController extends BladeController {
private final IRegionService regionService;
+
+ /**
+ * 鏂囦欢瀹夊叏妫�鏌�
+ */
+ @Autowired
+ private ComprehensiveFileValidator fileValidator;
/**
* 璇︽儏
@@ -170,6 +178,11 @@
@ApiOperationSupport(order = 10)
@ApiOperation(value = "瀵煎叆琛屾斂鍖哄垝", notes = "浼犲叆excel")
public R importRegion(MultipartFile file, Integer isCovered) {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.UploadValidationResult result = fileValidator.validateFile(file);
+ if (!result.isValid()) {
+ return R.fail(result.getMessage());
+ }
RegionImporter regionImporter = new RegionImporter(regionService, isCovered == 1);
ExcelUtil.save(file, regionImporter, RegionExcel.class);
return R.success("鎿嶄綔鎴愬姛");
diff --git a/Source/UBCS/ubcs-service/ubcs-user/src/main/java/com/vci/ubcs/system/user/controller/UserController.java b/Source/UBCS/ubcs-service/ubcs-user/src/main/java/com/vci/ubcs/system/user/controller/UserController.java
index 9bfdd3c..bf38725 100644
--- a/Source/UBCS/ubcs-service/ubcs-user/src/main/java/com/vci/ubcs/system/user/controller/UserController.java
+++ b/Source/UBCS/ubcs-service/ubcs-user/src/main/java/com/vci/ubcs/system/user/controller/UserController.java
@@ -21,6 +21,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.vci.ubcs.common.validator.ComprehensiveFileValidator;
import com.vci.ubcs.system.cache.NacosConfigCache;
import com.vci.ubcs.system.user.entity.User;
import com.vci.ubcs.system.user.excel.UserExcel;
@@ -32,8 +33,7 @@
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import com.vci.ubcs.common.cache.CacheNames;
-import org.apache.ibatis.annotations.Param;
-import org.hibernate.validator.internal.util.logging.Log;
+import lombok.extern.slf4j.Slf4j;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.mp.support.Condition;
@@ -50,6 +50,7 @@
import org.springblade.core.tool.utils.StringUtil;
import com.vci.ubcs.system.user.service.IUserService;
import com.vci.ubcs.system.user.vo.UserVO;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;
@@ -71,12 +72,19 @@
@RestController
@RequestMapping
@AllArgsConstructor
-@lombok.extern.java.Log
+@Slf4j
public class UserController {
private final IUserService userService;
+
private final BladeRedis bladeRedis;
+
private final NacosConfigCache nacosConfigCache;
+
+ /**
+ * 鏂囦欢瀹夊叏妫�鏌�
+ */
+ private ComprehensiveFileValidator fileValidator;
/**
* 鏌ヨ鍗曟潯
@@ -263,6 +271,11 @@
@ApiOperationSupport(order = 12)
@ApiOperation(value = "瀵煎叆鐢ㄦ埛", notes = "浼犲叆excel")
public R importUser(MultipartFile file, Integer isCovered) {
+ // 浣跨敤鏂囦欢瀹夊叏楠岃瘉鍣�
+ ComprehensiveFileValidator.UploadValidationResult result = fileValidator.validateFile(file);
+ if (!result.isValid()) {
+ return R.fail(result.getMessage());
+ }
UserImporter userImporter = new UserImporter(userService, isCovered == 1);
ExcelUtil.save(file, userImporter, UserExcel.class);
return R.success("鎿嶄綔鎴愬姛");
--
Gitblit v1.9.3