springcloud网关gateway过滤排除指定的路径【指定路径不过滤】

时间:2025-04-11 13:59:26

针对前面的网关渠道RSA加密,有些页面和接口需要不过滤;所以做了以下不过滤指定路径相关处理配置:

yml配置文件

agilepay:
  gateway:
    shouldSkipUrls:
      - /gatherpay/
      - /gatherpay/passive/callback
      - /gatherpay/static/webjars/**
      - /gatherpay/resources/webjars/
      - /gatherpay/resources/
      - /gatherpay/
      - /gatherpay/webjars/**
      - /gatherpay/
      - /gatherpay/swagger-resources
      - /gatherpay/v3/api-docs

配置文件:NotAuthUrlProperties

import ;
import ;
import ;

import ;

@Data
@Component
@ConfigurationProperties("")
public class NotAuthUrlProperties {

    private LinkedHashSet<String> shouldSkipUrls;
}

全局前置过滤器和后置过滤器中加入for循环判断

@Component
@Slf4j
public class WrapperRequestGlobalFilter implements GlobalFilter, Ordered {//, Ordered
    @Autowired
    private RsaKeyMapper rsaKeyMapper;

    @Resource
    private NotAuthUrlProperties notAuthUrlProperties;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = ();
        ServerHttpResponse response = ();

        String currentUrl = ().getURI().getPath();

        //1:不需要认证的url,不过滤放行的url
        if (shouldSkip(currentUrl)) {
            ("==========已跳过url{}=====", currentUrl);
            return (exchange);
        }
        ("===========网关请求解密开始==================");

        ServerRequest serverRequest = new DefaultServerRequest(exchange);
        //获取渠道id
        String channelId = ().getHeaders().getFirst("channelId");
        if (channelId != null) {
            //查看是否存在
            RsaKey rsaKeyTable = new LambdaQueryChainWrapper<>(rsaKeyMapper)
                    .eq(RsaKey::getChannelId, channelId).one();
            if (rsaKeyTable != null) {
                Mono<String> modifiedBody = ()
                        .flatMap(body -> {
                            //加密String转json对象
                            JSONObject jsonObject = (body);
                            String data = ("data");//获取加密数据值
                            //获取渠道对应支付私钥(其他项目传来的是用渠道对应支付公钥加密值)
                            String privateKeyPay = ();
                            (privateKeyPay + "私钥-------------");
                            try {
                                //私钥解密
                                String sp = (data, privateKeyPay);
                                // 解密后的值json字符串
                                String newBody = sp;
                                (newBody + "------------解密的值---------------------");
                                //TODO 获取body内容去干你想做的事
                                return (newBody);
                            } catch (Exception e) {
                                ();
                                //只要有异常就返回方法不允许
                                (HttpStatus.METHOD_NOT_ALLOWED);
                                //禁止访问
                                return ();
                            }
                        });


                BodyInserter bodyInserter = (modifiedBody, );
                HttpHeaders headers = new HttpHeaders();
                (().getHeaders());
                (HttpHeaders.CONTENT_LENGTH);
                CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
                return (outputMessage, new BodyInserterContext())
                        .then((() -> {
                            ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
                                    ()) {
                                @Override
                                public HttpHeaders getHeaders() {
                                    long contentLength = ();
                                    HttpHeaders httpHeaders = new HttpHeaders();
                                    (());
                                    if (contentLength > 0) {
                                        (contentLength);
                                    } else {
                                        (HttpHeaders.TRANSFER_ENCODING, "chunked");
                                    }
                                    return httpHeaders;
                                }

                                @Override
                                public Flux<DataBuffer> getBody() {
                                    return ();
                                }
                            };
                            return (().request(decorator).build());
                        }));
            } else {
                //如果rsaKeyTable==null 也不准访问
                return ().setComplete();
            }
        } else {
            ();
            //禁止访问
            return ().setComplete();
        }
//        }

    }


    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * 方法实现说明:不需要过滤的路径
     * <p>
     * //     * @param currentUrl 当前请求路径
     */
    private boolean shouldSkip(String currentUrl) {
        PathMatcher pathMatcher = new AntPathMatcher();
        for (String skipPath : ()) {
            if ((skipPath, currentUrl)) {
                return true;
            }
        }
        return false;
    }
}

import ;
import ;
import ;
import ;
import ;
import .slf4j.Slf4j;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;

import ;
import ;

@Component
@Slf4j
public class WrapperResponseGlobalFilter implements GlobalFilter, Ordered {
    @Autowired
    private RsaKeyMapper rsaKeyMapper;

    @Resource
    private NotAuthUrlProperties notAuthUrlProperties;

    @Override
    public int getOrder() {
        // -1 is response write filter, must be called before that
        return -1;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String currentUrl = ().getURI().getPath();
        //1:不需要认证的url
        if (shouldSkip(currentUrl)) {
            ("=====返回已跳过url{}===", currentUrl);
            return (exchange);
        }
        ("===============过滤返回值加密开始=====================");
        (().getPath().toString() + "----------------------------------");

        ServerHttpResponse originalResponse = ();
        DataBufferFactory bufferFactory = ();
        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                    return ((dataBuffer -> {
                        byte[] content = new byte[()];
                        (content);
                        //释放掉内存
                        (dataBuffer);
                        String s = new String(content, ("UTF-8"));
                        String channelId = ().getHeaders().getFirst("channelId");
                        RsaKey rsaKeyTable = new LambdaQueryChainWrapper<>(rsaKeyMapper)
                                .eq(RsaKey::getChannelId, channelId).one();
                        //通过渠道id获取对应渠道的公钥
                        String channelPublicKey = ();
                        //渠道私钥他们对应渠道自己有留存,不需要传||渠道对应的公私钥和支付项目的公私钥他们渠道那边都可以查到?根据渠道id,所以不需要传给他们,他们自己获取即可,我们传渠道公钥加密后的值就可以,他们那边用对应渠道私钥进行解密
                        ("过滤返回值明文:" + s);
                        String pubKeyEncrypt = "";
                        try {
                            pubKeyEncrypt = (s, channelPublicKey);
                        } catch (Exception e) {
                            ();
                        }
                        ("过滤返回值公钥加密:" + pubKeyEncrypt);
                        //TODO,s就是response的值,想修改、查看就随意而为了
                        byte[] uppedContent = ();//new String(content, ("UTF-8")).getBytes();
                        return (uppedContent);
                    }));
                }
                return (body);
            }
        };
        return (().response(decoratedResponse).build());
//        }
    }

    /**
     * 方法实现说明:不需要过滤的路径
     * <p>
     * //     * @param currentUrl 当前请求路径
     */
    private boolean shouldSkip(String currentUrl) {
        PathMatcher pathMatcher = new AntPathMatcher();
        ("===========需要跳过的地址==========:" + ());
        for (String skipPath : ()) {
            if ((skipPath, currentUrl)) {
                return true;
            }
        }
        return false;
    }
}

在过滤器中家的编码如下


   String currentUrl = ().getURI().getPath();

    //1:不需要认证的url,不过滤放行的url
        if (shouldSkip(currentUrl)) {
            ("==========已跳过url{}=====", currentUrl);
            return (exchange);
        }

    /**
     * 方法实现说明:不需要过滤的路径
     * <p>
     * //     * @param currentUrl 当前请求路径
     */
    private boolean shouldSkip(String currentUrl) {
        PathMatcher pathMatcher = new AntPathMatcher();
        for (String skipPath : ()) {
            if ((skipPath, currentUrl)) {
                return true;
            }
        }
        return false;
    }
}