- /gatherpay/passive/callback - /gatherpay/static/webjars/** - /gatherpay/resources/webjars/ - /gatherpay/resources/ - /gatherpay/swagger-ui.html - /gatherpay/webjars/** - /gatherpay/favicon.ico - /gatherpay/swagger-resources - /gatherpay/v3/api-docs

配置文件:NotAuthUrlProperties

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.LinkedHashSet;
@Data
@Component
@ConfigurationProperties("agilepay.gateway")
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 = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String currentUrl = exchange.getRequest().getURI().getPath();
        //1:不需要认证的url,不过滤放行的url
        if (shouldSkip(currentUrl)) {
            log.info("==========已跳过url{}=====", currentUrl);
            return chain.filter(exchange);
        log.info("===========网关请求解密开始==================");
        ServerRequest serverRequest = new DefaultServerRequest(exchange);
        //获取渠道id
        String channelId = exchange.getRequest().getHeaders().getFirst("channelId");
        if (channelId != null) {
            //查看是否存在
            RsaKey rsaKeyTable = new LambdaQueryChainWrapper<>(rsaKeyMapper)
                    .eq(RsaKey::getChannelId, channelId).one();
            if (rsaKeyTable != null) {
                Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
                        .flatMap(body -> {
                            //加密String转json对象
                            JSONObject jsonObject = JSONObject.parseObject(body);
                            String data = jsonObject.getString("data");//获取加密数据值
                            //获取渠道对应支付私钥(其他项目传来的是用渠道对应支付公钥加密值)
                            String privateKeyPay = rsaKeyTable.getRsaPrivatePayKey();
                            log.info(privateKeyPay + "私钥-------------");
                            try {
                                //私钥解密
                                String sp = EncryptUtil.decryptByPrivateKey(data, privateKeyPay);
                                // 解密后的值json字符串
                                String newBody = sp;
                                log.info(newBody + "------------解密的值---------------------");
                                //TODO 获取body内容去干你想做的事
                                return Mono.just(newBody);
                            } catch (Exception e) {
                                e.printStackTrace();
                                //只要有异常就返回方法不允许
                                response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED);
                                //禁止访问
                                return Mono.empty();
                BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
                HttpHeaders headers = new HttpHeaders();
                headers.putAll(exchange.getRequest().getHeaders());
                headers.remove(HttpHeaders.CONTENT_LENGTH);
                CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
                return bodyInserter.insert(outputMessage, new BodyInserterContext())
                        .then(Mono.defer(() -> {
                            ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
                                    exchange.getRequest()) {
                                @Override
                                public HttpHeaders getHeaders() {
                                    long contentLength = headers.getContentLength();
                                    HttpHeaders httpHeaders = new HttpHeaders();
                                    httpHeaders.putAll(super.getHeaders());
                                    if (contentLength > 0) {
                                        httpHeaders.setContentLength(contentLength);
                                    } else {
                                        httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
                                    return httpHeaders;
                                @Override
                                public Flux<DataBuffer> getBody() {
                                    return outputMessage.getBody();
                            return chain.filter(exchange.mutate().request(decorator).build());
            } else {
                //如果rsaKeyTable==null 也不准访问
                return exchange.getResponse().setComplete();
        } else {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            //禁止访问
            return exchange.getResponse().setComplete();
//        }
    @Override
    public int getOrder() {
        return 0;
     * 方法实现说明:不需要过滤的路径
     * //     * @param currentUrl 当前请求路径
    private boolean shouldSkip(String currentUrl) {
        PathMatcher pathMatcher = new AntPathMatcher();
        for (String skipPath : notAuthUrlProperties.getShouldSkipUrls()) {
            if (pathMatcher.match(skipPath, currentUrl)) {
                return true;
        return false;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.szzz.pay.agilepaygateway.properties.NotAuthUrlProperties;
import com.szzz.pay.agilepaygateway.rsakey.entity.RsaKey;
import com.szzz.pay.agilepaygateway.rsakey.mapper.RsaKeyMapper;
import com.szzz.pay.agilepaygateway.utils.EncryptUtil;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
import java.nio.charset.Charset;
@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 = exchange.getRequest().getURI().getPath();
        //1:不需要认证的url
        if (shouldSkip(currentUrl)) {
            log.info("=====返回已跳过url{}===", currentUrl);
            return chain.filter(exchange);
        log.info("===============过滤返回值加密开始=====================");
        log.info(exchange.getRequest().getPath().toString() + "----------------------------------");
        ServerHttpResponse originalResponse = exchange.getResponse();
        DataBufferFactory bufferFactory = originalResponse.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 super.writeWith(fluxBody.map(dataBuffer -> {
                        byte[] content = new byte[dataBuffer.readableByteCount()];
                        dataBuffer.read(content);
                        //释放掉内存
                        DataBufferUtils.release(dataBuffer);
                        String s = new String(content, Charset.forName("UTF-8"));
                        String channelId = exchange.getRequest().getHeaders().getFirst("channelId");
                        RsaKey rsaKeyTable = new LambdaQueryChainWrapper<>(rsaKeyMapper)
                                .eq(RsaKey::getChannelId, channelId).one();
                        //通过渠道id获取对应渠道的公钥
                        String channelPublicKey = rsaKeyTable.getRsaPublicKey();
                        //渠道私钥他们对应渠道自己有留存,不需要传||渠道对应的公私钥和支付项目的公私钥他们渠道那边都可以查到?根据渠道id,所以不需要传给他们,他们自己获取即可,我们传渠道公钥加密后的值就可以,他们那边用对应渠道私钥进行解密
                        log.info("过滤返回值明文:" + s);
                        String pubKeyEncrypt = "";
                        try {
                            pubKeyEncrypt = EncryptUtil.encryptByPublicKey(s, channelPublicKey);
                        } catch (Exception e) {
                            e.printStackTrace();
                        log.info("过滤返回值公钥加密:" + pubKeyEncrypt);
                        //TODO,s就是response的值,想修改、查看就随意而为了
                        byte[] uppedContent = pubKeyEncrypt.getBytes();//new String(content, Charset.forName("UTF-8")).getBytes();
                        return bufferFactory.wrap(uppedContent);
                return super.writeWith(body);
        return chain.filter(exchange.mutate().response(decoratedResponse).build());
//        }
     * 方法实现说明:不需要过滤的路径
     * //     * @param currentUrl 当前请求路径
    private boolean shouldSkip(String currentUrl) {
        PathMatcher pathMatcher = new AntPathMatcher();
        log.info("===========需要跳过的地址==========:" + notAuthUrlProperties.getShouldSkipUrls());
        for (String skipPath : notAuthUrlProperties.getShouldSkipUrls()) {
            if (pathMatcher.match(skipPath, currentUrl)) {
                return true;
        return false;

在过滤器中家的编码如下

String currentUrl = exchange.getRequest().getURI().getPath(); //1:不需要认证的url,不过滤放行的url if (shouldSkip(currentUrl)) { log.info("==========已跳过url{}=====", currentUrl); return chain.filter(exchange); * 方法实现说明:不需要过滤的路径 * // * @param currentUrl 当前请求路径 private boolean shouldSkip(String currentUrl) { PathMatcher pathMatcher = new AntPathMatcher(); for (String skipPath : notAuthUrlProperties.getShouldSkipUrls()) { if (pathMatcher.match(skipPath, currentUrl)) { return true; return false; 针对前面的网关渠道RSA加密,有些页面和接口需要不过滤;所以做了以下不过滤指定路径相关处理配置:yml配置文件application.ymlagilepay: gateway: shouldSkipUrls: - /gatherpay/doc.html - /gatherpay/passive/callback - /gatherpay/static/webjars/** - /gatherpay/resources/webjars/ Spring Cloud Gateway包含许多内置的路由断言Factories。这些断言都匹配HTTP请求的不同属性。 After 路由断言 After Route Predicate 在该日期时间之后发生的请求都将被匹配(UTC日期个数xxxx-xx-xxTxx:xx:xx+08:00[Asia/Shanghai]) spring: cloud: gateway: routes: - id: after_route
一:StripPrefix Filter 1.1 StripPrefix Filter 是一个请求路径截取的功能,我们可以利用这个功能来做特殊业务的转发。 1.2 修改 application-predicate-path.yml 文件,代码如下: server: port: 8769 #--- #三个横线表示再创建一个配置文件 spring: #profiles:...
2、Predicate(谓语、断言) 路由转发的判断条件,目前SpringCloud Gateway支持多种方式,常见如:Path、Query、Method、Header等,写法必须遵循 key=vlue的形式 3、Filter(过滤器) 过滤器是路由转发请求时所经过的过滤逻辑,可用于修改
路径匹配过滤配置 我们还可以根据请求路径实现对应的路由过滤操作,例如请求中以/brand/路径开始的请求,都直接交给http://localhost:180801服务处理,如下配置: routes: - id: changgou_goods_route uri: http://localhost:18081 predicates: - Path=/brand** 测试请求http://localhost:8001/brand,效果如下:
网关过滤GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理。 GatewayFilter Factories有30几个。 给所有进入userservice的请求添加一个请求头:Truth=NO.1 实现方式:在gateway中修改application.yml文件,给userservice的路由添加过滤器。 server: port: 10010 #网关端口 spring: application: name: geteway #服务
Spring Cloud Gateway是一个基于Spring Boot 2.x的API网关,可以通过GatewayFilter将请求路由到不同的目标服务。在GatewayFilter中,可以实现全局的过滤逻辑。全局过滤器可以拦截进入应用程序的请求,并在请求到达目标服务之前做一些逻辑处理。 Spring Cloud Gateway中的全局过滤器可以通过实现GlobalFilter接口或者实现GatewayFilterFactory接口来实现。GlobalFilter接口可以用来编写全局性质的过滤器,这类过滤器对所有路由的请求有效。GatewayFilterFactory则可以用来编写局部性质的过滤器,这类过滤器针对某个具体的路由或者路由组进行过滤。 全局过滤器可以实现许多不同的功能,例如:鉴权、日志记录、限流、请求缓存、请求转换等等。在实现全局过滤器时,需要注意过滤器执行的顺序,这也是Spring Cloud Gateway提供的另一种扩展机制,可以通过实现Ordered接口来控制过滤器的执行顺序。 总的来说,Spring Cloud Gateway全局过滤器是一个非常重要的特性,可以用于处理大量的系统级别的逻辑,使得开发人员可以将更多精力集中在业务层面的开发。