Ludc
2025-11-18 17925215d37dd97d744c9296b185aeb16d3e44fb
URL请求路径安全校验
已添加1个文件
已修改3个文件
已删除1个文件
213 ■■■■ 文件已修改
Source/UBCS/pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-common/src/main/java/com/vci/ubcs/common/constant/LauncherConstant.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-gateway/src/main/java/com/vci/ubcs/gateway/filter/EssentialSecurityFilter.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-gateway/src/main/java/com/vci/ubcs/gateway/filter/GlobalUrlSecurityFilter.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/controller/FlowManagerController.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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>
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 åœ°å€
Source/UBCS/ubcs-gateway/src/main/java/com/vci/ubcs/gateway/filter/EssentialSecurityFilter.java
ÎļþÒÑɾ³ý
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;
    // å±é™©å­—符正则表达式
    @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 {
            // ç¼–译危险字符正则表达式
            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;
    }
}
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,