From 17925215d37dd97d744c9296b185aeb16d3e44fb Mon Sep 17 00:00:00 2001
From: Ludc <2870569285@qq.com>
Date: 星期二, 18 十一月 2025 20:06:12 +0800
Subject: [PATCH] URL请求路径安全校验

---
 /dev/null                                                                                                   |   42 ----------
 Source/UBCS/ubcs-gateway/src/main/java/com/vci/ubcs/gateway/filter/GlobalUrlSecurityFilter.java             |  142 +++++++++++++++++++++++++++++++++++
 Source/UBCS/pom.xml                                                                                         |    5 
 Source/UBCS/ubcs-common/src/main/java/com/vci/ubcs/common/constant/LauncherConstant.java                    |   12 +-
 Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/controller/FlowManagerController.java |   12 +-
 5 files changed, 157 insertions(+), 56 deletions(-)

diff --git a/Source/UBCS/pom.xml b/Source/UBCS/pom.xml
index c58d13a..79bfe13 100644
--- a/Source/UBCS/pom.xml
+++ b/Source/UBCS/pom.xml
@@ -108,11 +108,11 @@
             <resource>
                 <directory>src/main/resources</directory>
                 <excludes>
-                    <!--<exclude>bootstrap.yml</exclude>
+                    <exclude>bootstrap.yml</exclude>
                     <exclude>application.yml</exclude>
                     <exclude>application-dev.yml</exclude>
                     <exclude>application-test.yml</exclude>
-                    <exclude>application-prop.yml</exclude>-->
+                    <exclude>application-prop.yml</exclude>
                 </excludes>
             </resource>
             <resource>
@@ -205,6 +205,7 @@
                         <excludes>
                             <exclude>application-dev.yml</exclude>
                             <exclude>application-prod.yml</exclude>
+                            <exclude>application-test.yml</exclude>
                             <exclude>application.yml</exclude>
                             <exclude>lib/*</exclude>
                         </excludes>
diff --git a/Source/UBCS/ubcs-common/src/main/java/com/vci/ubcs/common/constant/LauncherConstant.java b/Source/UBCS/ubcs-common/src/main/java/com/vci/ubcs/common/constant/LauncherConstant.java
index 03010fc..a17a3b0 100644
--- a/Source/UBCS/ubcs-common/src/main/java/com/vci/ubcs/common/constant/LauncherConstant.java
+++ b/Source/UBCS/ubcs-common/src/main/java/com/vci/ubcs/common/constant/LauncherConstant.java
@@ -40,20 +40,20 @@
 	/**
 	 * nacos dev 鍦板潃
 	 */
-	//String NACOS_DEV_ADDR = "dev.vci-tech.com:38848";
-	String NACOS_DEV_ADDR = "127.0.0.1:8848";
+	String NACOS_DEV_ADDR = "dev.vci-tech.com:38848";
+	//String NACOS_DEV_ADDR = "127.0.0.1:8848";
 
 	/**
 	 * nacos prod 鍦板潃
 	 */
-	//String NACOS_PROD_ADDR = "dev.vci-tech.com:38848";
-	String NACOS_PROD_ADDR = "127.0.0.1:8848";
+	String NACOS_PROD_ADDR = "dev.vci-tech.com:38848";
+	//String NACOS_PROD_ADDR = "127.0.0.1:8848";
 
 	/**
 	 * nacos test 鍦板潃
 	 */
-	//String NACOS_TEST_ADDR = "dev.vci-tech.com:38848";
-	String NACOS_TEST_ADDR = "127.0.0.1:8848";
+	String NACOS_TEST_ADDR = "dev.vci-tech.com:38848";
+	//String NACOS_TEST_ADDR = "127.0.0.1:8848";
 
 	/**
 	 * sentinel dev 鍦板潃
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
deleted file mode 100644
index 9813539..0000000
--- a/Source/UBCS/ubcs-gateway/src/main/java/com/vci/ubcs/gateway/filter/EssentialSecurityFilter.java
+++ /dev/null
@@ -1,42 +0,0 @@
-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-gateway/src/main/java/com/vci/ubcs/gateway/filter/GlobalUrlSecurityFilter.java b/Source/UBCS/ubcs-gateway/src/main/java/com/vci/ubcs/gateway/filter/GlobalUrlSecurityFilter.java
new file mode 100644
index 0000000..642af93
--- /dev/null
+++ b/Source/UBCS/ubcs-gateway/src/main/java/com/vci/ubcs/gateway/filter/GlobalUrlSecurityFilter.java
@@ -0,0 +1,142 @@
+package com.vci.ubcs.gateway.filter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import javax.annotation.PostConstruct;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+/**
+ * 鍏ㄥ眬URL瀹夊叏杩囨护鍣� - 瀵规墍鏈夎姹傜敓鏁�
+ * 鐩存帴浣跨敤@Value娉ㄨВ璇诲彇閰嶇疆
+ */
+@Component
+public class GlobalUrlSecurityFilter implements GlobalFilter, Ordered {
+	private static final Logger log = LoggerFactory.getLogger(GlobalUrlSecurityFilter.class);
+
+	// 鏄惁鍚敤URL瀹夊叏杩囨护鍣�
+	@Value("${gateway.security.url.enabled:true}")
+	private boolean enabled;
+
+	// 鍗遍櫓瀛楃姝e垯琛ㄨ揪寮�
+	@Value("${gateway.security.url.dangerous-pattern:<script|</script|javascript:|onload|onerror|onclick|union.*select|select.*from|[\"';<>\\x00-\\x1F\\x7F]|%3C|%3E|%27|%22|%00|\\.\\./|\\.\\.\\\\}")
+	private String dangerousPattern;
+
+	// 鐧藉悕鍗曡矾寰�
+	@Value("${gateway.security.url.whitelist-paths:/health,/actuator/health,/actuator/info,/favicon.ico}")
+	private String[] whitelistPaths;
+
+	private Pattern compiledPattern;
+
+	private Set<String> whitelistSet;
+
+	/**
+	 * 鍒濆鍖栨柟娉�
+	 */
+	@PostConstruct
+	public void init() {
+		try {
+			// 缂栬瘧鍗遍櫓瀛楃姝e垯琛ㄨ揪寮�
+			this.compiledPattern = Pattern.compile(dangerousPattern, Pattern.CASE_INSENSITIVE);
+
+			// 鍒濆鍖栫櫧鍚嶅崟闆嗗悎
+			this.whitelistSet = new HashSet<>(Arrays.asList(whitelistPaths));
+
+			log.info("鍏ㄥ眬URL瀹夊叏杩囨护鍣ㄥ垵濮嬪寲瀹屾垚");
+			log.info("杩囨护鍣ㄧ姸鎬�: {}", enabled ? "宸插惎鐢�" : "宸茬鐢�");
+			log.info("鐧藉悕鍗曡矾寰�: {}", whitelistSet);
+
+		} catch (Exception e) {
+			log.error("鍒濆鍖栬繃婊ゅ櫒澶辫触", e);
+			// 浣跨敤榛樿閰嶇疆浣滀负鍚庡
+			this.compiledPattern = Pattern.compile(
+				"<script|</script|javascript:|onload|onerror|onclick|union.*select|select.*from|[\"';<>\\x00-\\x1F\\x7F]|%3C|%3E|%27|%22|%00|\\.\\./|\\.\\.\\\\",
+				Pattern.CASE_INSENSITIVE
+			);
+			this.whitelistSet = new HashSet<>(Arrays.asList(
+				"/health", "/actuator/health", "/actuator/info", "/favicon.ico"
+			));
+		}
+	}
+
+	@Override
+	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+		// 妫�鏌ユ槸鍚﹀惎鐢ㄨ繃婊ゅ櫒
+		if (!enabled) {
+			return chain.filter(exchange);
+		}
+
+		ServerHttpRequest request = exchange.getRequest();
+		String path = request.getURI().getPath();
+		String method = request.getMethod().name();
+
+		// 妫�鏌ョ櫧鍚嶅崟璺緞
+		if (isWhitelistedPath(path)) {
+			return chain.filter(exchange);
+		}
+
+		// 楠岃瘉璺緞瀹夊叏鎬�
+		if (!isPathSafe(path)) {
+			log.warn("鎷︽埅鍗遍櫓璇锋眰: {} {}", method, request.getURI());
+			exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
+			return exchange.getResponse().setComplete();
+		}
+
+		return chain.filter(exchange);
+	}
+
+	@Override
+	public int getOrder() {
+		return Ordered.HIGHEST_PRECEDENCE;
+	}
+
+	/**
+	 * 楠岃瘉璺緞瀹夊叏鎬�
+	 */
+	private boolean isPathSafe(String path) {
+		if (path == null || path.isEmpty()) {
+			return true;
+		}
+
+		// 妫�鏌ヨ矾寰勯亶鍘�
+		if (path.contains("../") || path.contains("..\\")) {
+			return false;
+		}
+
+		// 妫�鏌ュ嵄闄╁瓧绗�
+		if (compiledPattern.matcher(path).find()) {
+			return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * 妫�鏌ヨ矾寰勬槸鍚﹀湪鐧藉悕鍗曚腑
+	 */
+	private boolean isWhitelistedPath(String path) {
+		if (path == null) {
+			return false;
+		}
+
+		for (String whitelistPath : whitelistSet) {
+			if (path.startsWith(whitelistPath) || path.equals(whitelistPath)) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+}
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 c46518a..e435680 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
@@ -46,7 +46,7 @@
  */
 @NonDS
 @RestController
-@RequestMapping("manager")
+@RequestMapping("/manager")
 @AllArgsConstructor
 @Api(value = "娴佺▼绠$悊鎺ュ彛", tags = "娴佺▼绠$悊鎺ュ彛")
 public class FlowManagerController {
@@ -62,7 +62,7 @@
 	/**
 	 * 鍒嗛〉
 	 */
-	@GetMapping("list")
+	@GetMapping("/list")
 	@ApiOperationSupport(order = 1)
 	@ApiOperation(value = "鍒嗛〉", notes = "浼犲叆娴佺▼绫诲瀷")
 	public R<IPage<FlowProcess>> list(@ApiParam("娴佺▼绫诲瀷") String category, Query query, @RequestParam(required = false, defaultValue = "1") Integer mode) {
@@ -76,7 +76,7 @@
 	 * @param state     鐘舵��
 	 * @param processId 娴佺▼id
 	 */
-	@PostMapping("change-state")
+	@PostMapping("/change-state")
 	@ApiOperationSupport(order = 2)
 	@ApiOperation(value = "鍙樻洿娴佺▼鐘舵��", notes = "浼犲叆state,processId")
 	public R changeState(@RequestParam String state, @RequestParam String processId) {
@@ -89,7 +89,7 @@
 	 *
 	 * @param deploymentIds 閮ㄧ讲娴佺▼id闆嗗悎
 	 */
-	@PostMapping("delete-deployment")
+	@PostMapping("/delete-deployment")
 	@ApiOperationSupport(order = 3)
 	@ApiOperation(value = "鍒犻櫎閮ㄧ讲娴佺▼", notes = "閮ㄧ讲娴佺▼id闆嗗悎")
 	public R deleteDeployment(String deploymentIds) {
@@ -101,7 +101,7 @@
 	 *
 	 * @param file 娴佺▼鏂囦欢
 	 */
-	@PostMapping("check-upload")
+	@PostMapping("/check-upload")
 	@ApiOperationSupport(order = 4)
 	@ApiOperation(value = "涓婁紶閮ㄧ讲娴佺▼鏂囦欢", notes = "浼犲叆鏂囦欢")
 	public R checkUpload(@RequestParam MultipartFile file) {
@@ -120,7 +120,7 @@
 	 * @param files    娴佺▼鏂囦欢
 	 * @param category 绫诲瀷
 	 */
-	@PostMapping("deploy-upload")
+	@PostMapping("/deploy-upload")
 	@ApiOperationSupport(order = 5)
 	@ApiOperation(value = "涓婁紶閮ㄧ讲娴佺▼鏂囦欢", notes = "浼犲叆鏂囦欢")
 	public R deployUpload(@RequestParam List<MultipartFile> files,

--
Gitblit v1.9.3