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