• spring geteway 网关代理HTTPS http转HTTPS


    geteway 代理HTTPS 中遇到这样的错误
    在这里插入图片描述

    2022-09-11 10:53:13.988 ERROR 9612 --- [ctor-http-nio-4] o.s.w.s.adapter.HttpWebHandlerAdapter    : [c3543410-2] 500 Server Error for HTTP GET "/auth/w"
    
    javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    	at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1478) ~[na:1.8.0_151]
    	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
    Error has been observed at the following site(s):
    	|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
    	|_ checkpoint ⇢ HTTP GET "/auth/w" [ExceptionHandlingWebHandler]
    Stack trace:
    		at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1478) ~[na:1.8.0_151]
    		at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:535) ~[na:1.8.0_151]
    		at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:813) ~[na:1.8.0_151]
    		at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781) ~[na:1.8.0_151]
    		at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624) ~[na:1.8.0_151]
    		at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:282) ~[netty-handler-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1387) [netty-handler-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1282) [netty-handler-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1329) [netty-handler-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508) ~[netty-codec-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447) ~[netty-codec-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
    		at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.58.Final.jar:4.1.58.Final]
    		at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_151]
    Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[na:1.8.0_151]
    	at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1728) ~[na:1.8.0_151]
    	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:304) ~[na:1.8.0_151]
    	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296) ~[na:1.8.0_151]
    	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1514) ~[na:1.8.0_151]
    	at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216) ~[na:1.8.0_151]
    	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026) ~[na:1.8.0_151]
    	at sun.security.ssl.Handshaker$1.run(Handshaker.java:966) ~[na:1.8.0_151]
    	at sun.security.ssl.Handshaker$1.run(Handshaker.java:963) ~[na:1.8.0_151]
    	at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_151]
    	at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1416) ~[na:1.8.0_151]
    	at io.netty.handler.ssl.SslHandler.runAllDelegatedTasks(SslHandler.java:1557) [netty-handler-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1571) [netty-handler-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1455) [netty-handler-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1282) [netty-handler-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1329) [netty-handler-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508) ~[netty-codec-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447) ~[netty-codec-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.58.Final.jar:4.1.58.Final]
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    解决方案

    spring:
      cloud:
                # 信任所有证书
        gateway:
          httpclient:
            ssl:
              use-insecure-trust-manager: true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    重写https HttpClient bean 方法

    package com.qz.mos.config;
    
    import io.netty.channel.ChannelOption;
    import io.netty.handler.ssl.SslContextBuilder;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.boot.context.properties.PropertyMapper;
    import org.springframework.cloud.gateway.config.HttpClientCustomizer;
    import org.springframework.cloud.gateway.config.HttpClientProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.annotation.AnnotationAwareOrderComparator;
    import org.springframework.util.CollectionUtils;
    import org.springframework.util.StringUtils;
    import reactor.netty.http.client.HttpClient;
    import reactor.netty.resources.ConnectionProvider;
    import reactor.netty.tcp.ProxyProvider;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.time.Duration;
    import java.util.List;
    
    import static org.springframework.cloud.gateway.config.HttpClientProperties.Pool.PoolType.DISABLED;
    import static org.springframework.cloud.gateway.config.HttpClientProperties.Pool.PoolType.FIXED;
    
    /**
     * 覆盖gateway默认的httpClient配置 支持jks格式的证书
     * 
     * @author 易通
     * @since 2022/9/11
     */
    @Configuration
    @Slf4j
    public class GatewayHttpClientConfig {
        protected final Log logger = LogFactory.getLog(getClass());
    
        @Bean
        public HttpClient gatewayHttpClient(HttpClientProperties properties,
                                            List<HttpClientCustomizer> customizers) {
    
            // configure pool resources
            ConnectionProvider connectionProvider = buildConnectionProvider(properties);
    
            HttpClient httpClient = HttpClient.create(connectionProvider)
                    // TODO: move customizations to HttpClientCustomizers
                    .httpResponseDecoder(spec -> {
                        if (properties.getMaxHeaderSize() != null) {
                            // cast to int is ok, since @Max is Integer.MAX_VALUE
                            spec.maxHeaderSize(
                                    (int) properties.getMaxHeaderSize().toBytes());
                        }
                        if (properties.getMaxInitialLineLength() != null) {
                            // cast to int is ok, since @Max is Integer.MAX_VALUE
                            spec.maxInitialLineLength(
                                    (int) properties.getMaxInitialLineLength().toBytes());
                        }
                        return spec;
                    }).tcpConfiguration(tcpClient -> {
    
                        if (properties.getConnectTimeout() != null) {
                            tcpClient = tcpClient.option(
                                    ChannelOption.CONNECT_TIMEOUT_MILLIS,
                                    properties.getConnectTimeout());
                        }
    
                        // configure proxy if proxy host is set.
                        HttpClientProperties.Proxy proxy = properties.getProxy();
    
                        if (StringUtils.hasText(proxy.getHost())) {
    
                            tcpClient = tcpClient.proxy(proxySpec -> {
                                ProxyProvider.Builder builder = proxySpec
                                        .type(ProxyProvider.Proxy.HTTP)
                                        .host(proxy.getHost());
    
                                PropertyMapper map = PropertyMapper.get();
    
                                map.from(proxy::getPort).whenNonNull().to(builder::port);
                                map.from(proxy::getUsername).whenHasText()
                                        .to(builder::username);
                                map.from(proxy::getPassword).whenHasText()
                                        .to(password -> builder.password(s -> password));
                                map.from(proxy::getNonProxyHostsPattern).whenHasText()
                                        .to(builder::nonProxyHosts);
                            });
                        }
                        return tcpClient;
                    });
    
            HttpClientProperties.Ssl ssl = properties.getSsl();
            if ((ssl.getKeyStore() != null && ssl.getKeyStore().length() > 0)
                    || ssl.getTrustedX509CertificatesForTrustManager().length > 0
                    || ssl.isUseInsecureTrustManager()) {
                httpClient = httpClient.secure(sslContextSpec -> {
                    // configure ssl
                    SslContextBuilder sslContextBuilder = SslContextBuilder.forClient();
    
                    X509Certificate[] trustedX509Certificates = ssl
                            .getTrustedX509CertificatesForTrustManager();
                    if (trustedX509Certificates.length > 0) {
                        sslContextBuilder = sslContextBuilder
                                .trustManager(trustedX509Certificates);
                    }
                    else if (ssl.isUseInsecureTrustManager()) {
                        X509TrustManager tm = new X509TrustManager() {
                            @Override
                            public void checkClientTrusted(X509Certificate[] chain,
                                                           String authType) throws CertificateException {
                            }
                            @Override
                            public void checkServerTrusted(X509Certificate[] chain,
                                                           String authType) throws CertificateException {
                            }
                            @Override
                            public X509Certificate[] getAcceptedIssuers() {
                                return null;
                            }
                        };
                        sslContextBuilder = sslContextBuilder.trustManager(tm);
                    }
    
                    try {
                        sslContextBuilder = sslContextBuilder
                                .keyManager(ssl.getKeyManagerFactory());
                    }
                    catch (Exception e) {
                        logger.error(e);
                    }
    
                    sslContextSpec.sslContext(sslContextBuilder)
                            .defaultConfiguration(ssl.getDefaultConfigurationType())
                            .handshakeTimeout(ssl.getHandshakeTimeout())
                            .closeNotifyFlushTimeout(ssl.getCloseNotifyFlushTimeout())
                            .closeNotifyReadTimeout(ssl.getCloseNotifyReadTimeout());
                });
            }
    
            if (properties.isWiretap()) {
                httpClient = httpClient.wiretap(true);
            }
    
            if (properties.isCompression()) {
                httpClient = httpClient.compress(true);
            }
    
            if (!CollectionUtils.isEmpty(customizers)) {
                customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
                for (HttpClientCustomizer customizer : customizers) {
                    httpClient = customizer.customize(httpClient);
                }
            }
    
            return httpClient;
        }
    
        private ConnectionProvider buildConnectionProvider(
                HttpClientProperties properties) {
            HttpClientProperties.Pool pool = properties.getPool();
    
            ConnectionProvider connectionProvider;
            if (pool.getType() == DISABLED) {
                connectionProvider = ConnectionProvider.newConnection();
            }
            else {
                // create either Fixed or Elastic pool
                ConnectionProvider.Builder builder = ConnectionProvider
                        .builder(pool.getName());
                if (pool.getType() == FIXED) {
                    builder.maxConnections(pool.getMaxConnections())
                            .pendingAcquireMaxCount(-1).pendingAcquireTimeout(
                            Duration.ofMillis(pool.getAcquireTimeout()));
                }
                else {
                    // Elastic
                    builder.maxConnections(Integer.MAX_VALUE)
                            .pendingAcquireTimeout(Duration.ofMillis(0))
                            .pendingAcquireMaxCount(-1);
                }
    
                if (pool.getMaxIdleTime() != null) {
                    builder.maxIdleTime(pool.getMaxIdleTime());
                }
                if (pool.getMaxLifeTime() != null) {
                    builder.maxLifeTime(pool.getMaxLifeTime());
                }
                builder.evictInBackground(pool.getEvictionInterval());
                connectionProvider = builder.build();
            }
            return connectionProvider;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198

    各位老铁点赞加关注,不能白嫖啊!

  • 相关阅读:
    [附源码]计算机毕业设计springboot班级事务管理论文2022
    Deno完整教程
    QGroupBox 类(组框)
    GO语言常用标准库 fmt
    GB/T 29734.3-2020 塑钢复合门窗检测
    用户头像(图片文件)上传(Vue + nodejs 前后端)
    mysql基础_索引
    Typestript核心——接口interface,类类型,类接口,继承接口
    视频汇聚管理平台EasyCVR程序报错“create jwtSecret del server class:0xf98b6040”的原因排查与解决
    python opencv2滚轮快速切换图片
  • 原文地址:https://blog.csdn.net/qq_40127376/article/details/126803264