netty-ssl / tls双向身份验证

时间:2019-01-26 17:28:36

标签: netty android-9.0-pie

我已经尝试过Two way SSL authentication in Netty

,但是该示例不再显示任何信息,仅显示404 Not Found。我在这里找到了一些帮助:

https://github.com/code4craft/netty-learning/blob/master/netty-3.7/src/main/java/org/jboss/netty/example/securechat/SecureChatSslContextFactory.java

尽管我的代码没有使用与sslchat完全相同的api调用(将管理者添加到init的顺序),但我的代码在执行所有操作后仍然失败。

这是我的代码和错误。该错误并不表示它是哪个ssl / tls错误。我仅使用一种身份验证和加密方法检查了两个证书/私钥(针对客户端/服务器的两个方面),并且可以正常工作。

服务器端代码:

    KeyStore serverKeyStore = handleServerKeystore(sipListener);
KeyManagerFactory serverKmf = KeyManagerFactory
                                            .getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore clientKeyStore = KeyStore.getInstance("JKS");
clientKeyStore.load(null, SipListener.KEYSTORE_PASSWORD.toCharArray());
for (ClientCertificate clientCertCert : sipListener.getClientCertificates()) {
Certificate clientCert = CertificateFactory.getInstance("X.509")
                                                .generateCertificate(new ByteArrayInputStream(
                                                        clientCertCert.getClientCertificate().getBytes()));
                                        clientKeyStore.setCertificateEntry(clientCertCert.getClientCertificateAlias(),
                                                clientCert);
                                    }

KeyStore.Builder serverBuilder = KeyStore.Builder.newInstance(serverKeyStore,
                                            new KeyStore.PasswordProtection(SipListener.KEYSTORE_PASSWORD.toCharArray()));
KeyStore.Builder clientBuilder = KeyStore.Builder.newInstance(clientKeyStore,
                                            new KeyStore.PasswordProtection(SipListener.KEYSTORE_PASSWORD.toCharArray()));
                                    serverKmf.init(new KeyStoreBuilderParameters(
                                            Arrays.asList(new KeyStore.Builder[] { serverBuilder, clientBuilder })));

// Initialize the SSLContext to work with our key managers.
SslContext serverContext = SslContextBuilder.forServer(serverKmf).build();

SSLEngine sslEngine = serverContext.newEngine(ch.alloc());
SSLParameters params = new SSLParameters();
List<SNIMatcher> matchers = new LinkedList<>();
SNIMatcher matcher = new SNIMatcher(0) {

                                        @Override
                                        public boolean matches(SNIServerName serverName) {
                                            return true;
                                        }
                                    };
matchers.add(matcher);
params.setSNIMatchers(matchers);
sslEngine.setSSLParameters(params);
//sslEngine.setUseClientMode(false);
sslEngine.setNeedClientAuth(true);
cp.addFirst("ssl", new SslHandler(sslEngine));
//More codecs follow

客户端代码:

SslContextBuilder sslBuilder = SslContextBuilder.forClient();
SslContext cont2 = null;
KeyManagerFactory keyManagerFactory = KeyManagerFactory
                                .getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore serverKeyStore = KeyStore.getInstance("BKS");
serverKeyStore.load(
                                new ByteArrayInputStream(
                                        decoder.decode(sipSettingsBean.getSipSettingsServerBeans().get(0).getKeystoreB64().getBytes())),
SipListener.KEYSTORE_PASSWORD.toCharArray());
if (!serverKeyStore.isKeyEntry(sipSettingsBean.getSipSettingsServerBeans().get(0).getKeystoreAlias()))
                            throw new IllegalArgumentException(
                                    "Server Keystore file has no matching key for given alias.");
keyManagerFactory.init(serverKeyStore,
                                SipListener.KEYSTORE_PASSWORD.toCharArray());
sslBuilder.keyManager(keyManagerFactory);

TrustManagerFactory trustManagerFactory = TrustManagerFactory
                                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
// truststore
KeyStore clientKeyStore = KeyStore.getInstance("BKS");
clientKeyStore.load(null, SipListener.KEYSTORE_PASSWORD.toCharArray());
for (Cert clientCertCert : sipSettingsBean.getSipSettingsServerBeans().get(0).getCerts()) {
Certificate clientCert = CertificateFactory.getInstance("X.509")
                                    .generateCertificate(new ByteArrayInputStream(
                                            clientCertCert.getCert().getBytes()));
clientKeyStore.setCertificateEntry(
                                    clientCertCert.getAlias(), clientCert);
if (!clientKeyStore.isCertificateEntry(clientCertCert.getAlias()))
                                throw new IllegalArgumentException(
                                        "Client Keystore file has no matching key for given alias.");
                        }

trustManagerFactory.init(clientKeyStore);
sslBuilder.trustManager(trustManagerFactory);

cont2 = sslBuilder.build();
SSLEngine engine = cont2.newEngine(ch.alloc(), toHostname,
                                portDestination);
engine.setEnabledProtocols(new String[]{"TLSv1.2"});
SSLParameters params = new SSLParameters();
List<SNIMatcher> matchers = new LinkedList<>();
SNIMatcher matcher = new SNIMatcher(0) {

                            @Override
                            public boolean matches(SNIServerName serverName) {
                              return true;
                            }
                        };
matchers.add(matcher);
params.setSNIMatchers(matchers);
engine.setSSLParameters(params);
ch.pipeline().addLast("ssl", new SslHandler(engine, false));
//More codecs follow

客户端错误:

2019-01-26 18:18:54.784 31491-31672/xx.xxxxxxxxxx.xxxxxxxxx D/no.tobiassenit.sipclient.network.RegisterAttemptSSL: request sent
2019-01-26 18:18:54.786 31491-31672/xx.xxxxxxxxxx.xxxxxxxxx D/no.tobiassenit.sipclient.network.RegisterAttemptSSL: request did not time out
2019-01-26 18:18:54.789 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err: io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Read error: ssl=0x774f846f08: Failure in SSL library, usually a protocol error
2019-01-26 18:18:54.789 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err: error:10000412:SSL routines:OPENSSL_internal:SSLV3_ALERT_BAD_CERTIFICATE (external/boringssl/src/ssl/tls_record.cc:592 0x774f890d08:0x00000001)
2019-01-26 18:18:54.789 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:459)
2019-01-26 18:18:54.790 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)
2019-01-26 18:18:54.790 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
2019-01-26 18:18:54.790 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
2019-01-26 18:18:54.790 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
2019-01-26 18:18:54.790 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
2019-01-26 18:18:54.790 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
2019-01-26 18:18:54.790 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
2019-01-26 18:18:54.790 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
2019-01-26 18:18:54.790 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
2019-01-26 18:18:54.791 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:646)
2019-01-26 18:18:54.791 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:581)
2019-01-26 18:18:54.791 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:498)
2019-01-26 18:18:54.791 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:460)
2019-01-26 18:18:54.791 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
2019-01-26 18:18:54.791 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
2019-01-26 18:18:54.791 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at java.lang.Thread.run(Thread.java:764)
2019-01-26 18:18:54.792 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err: Caused by: javax.net.ssl.SSLHandshakeException: Read error: ssl=0x774f846f08: Failure in SSL library, usually a protocol error
2019-01-26 18:18:54.792 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err: error:10000412:SSL routines:OPENSSL_internal:SSLV3_ALERT_BAD_CERTIFICATE (external/boringssl/src/ssl/tls_record.cc:592 0x774f890d08:0x00000001)
2019-01-26 18:18:54.792 31491-31771/v W/System.err:     at com.android.org.conscrypt.SSLUtils.toSSLHandshakeException(SSLUtils.java:331)
2019-01-26 18:18:54.792 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at com.android.org.conscrypt.ConscryptEngine.convertException(ConscryptEngine.java:1138)
2019-01-26 18:18:54.792 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:893)
2019-01-26 18:18:54.792 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:713)
2019-01-26 18:18:54.792 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:678)
2019-01-26 18:18:54.793 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at com.android.org.conscrypt.Java8EngineWrapper.unwrap(Java8EngineWrapper.java:236)
2019-01-26 18:18:54.793 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:294)
2019-01-26 18:18:54.793 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1275)
2019-01-26 18:18:54.793 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1177)
2019-01-26 18:18:54.793 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1221)
2019-01-26 18:18:54.793 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)
2019-01-26 18:18:54.793 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428)
2019-01-26 18:18:54.793 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:   ... 16 more
2019-01-26 18:18:54.794 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err: Caused by: javax.net.ssl.SSLProtocolException: Read error: ssl=0x774f846f08: Failure in SSL library, usually a protocol error
2019-01-26 18:18:54.794 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err: error:10000412:SSL routines:OPENSSL_internal:SSLV3_ALERT_BAD_CERTIFICATE (external/boringssl/src/ssl/tls_record.cc:592 0x774f890d08:0x00000001)
2019-01-26 18:18:54.794 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at com.android.org.conscrypt.NativeCrypto.ENGINE_SSL_read_direct(Native Method)
2019-01-26 18:18:54.794 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at com.android.org.conscrypt.NativeSsl.readDirectByteBuffer(NativeSsl.java:521)
2019-01-26 18:18:54.794 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at com.android.org.conscrypt.ConscryptEngine.readPlaintextDataDirect(ConscryptEngine.java:1099)
2019-01-26 18:18:54.794 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at com.android.org.conscrypt.ConscryptEngine.readPlaintextDataHeap(ConscryptEngine.java:1119)
2019-01-26 18:18:54.795 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1091)
2019-01-26 18:18:54.795 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:     at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:841)
2019-01-26 18:18:54.795 31491-31771/xx.xxxxxxxxxx.xxxxxxxxx W/System.err:   ... 25 more

服务器端错误:

 io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: null cert chain
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:459)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:646)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:581)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:498)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:460)
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.lang.Thread.run(Thread.java:748)Caused by: javax.net.ssl.SSLHandshakeException: null cert chain
    at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1441)
    at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:535)
    at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:813)
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781)
    at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
    at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:294)
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1275)
    at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1177)
    at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1221)
    at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428)
    ... 16 moreCaused by: javax.net.ssl.SSLHandshakeException: null cert chain
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:201)
    at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1672)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:309)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:297)
    at sun.security.ssl.ServerHandshaker.clientCertificate(ServerHandshaker.java:1942)
    at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:236)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:984)
    at sun.security.ssl.Handshaker$1.run(Handshaker.java:924)
    at sun.security.ssl.Handshaker$1.run(Handshaker.java:921)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1379)
    at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1435)
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1343)
    ... 20 more

|

当然:净值:4.1.28.Final,Win10和Java版本“ 1.8.0_151”

我尝试了netty 4.1.33.Final。结果相同。

您可能已经注意到,我已经忽略了引擎中主机名的测试。这可能仅用于服务器握手,而不用于客户端(专用密钥)握手。请提出建议,如果您也可以忽略握手的客户端主机名部分,除非它已经完成(我已经尝试过在两面都这样做),否则我的应用程序将无法支持该客户端的dns名称。 (它将能够为服务器提供支持,但暂时不支持它。)

我尝试过netty 4.1.34.Final-20190208.192045-20。结果相同。 我尝试了netty 4.1.34.Final。结果相同。 我尝试过netty 4.1.35.Final-SNAPSHOT。结果相同。

1 个答案:

答案 0 :(得分:0)

我在用Netty执行双向SSL时遇到了这个问题。我通过使用以下配置解决了该问题:

public HttpClient getHttpClient(HttpClientProperties properties){

        // configure pool resources
        HttpClientProperties.Pool pool = properties.getPool();

        ConnectionProvider connectionProvider;
        if (pool.getType() == DISABLED) {
            connectionProvider = ConnectionProvider.newConnection();
        }
        else if (pool.getType() == FIXED) {
            connectionProvider = ConnectionProvider.fixed(pool.getName(),
                    pool.getMaxConnections(), pool.getAcquireTimeout());
        }
        else {
            connectionProvider = ConnectionProvider.elastic(pool.getName());
        }

        HttpClient httpClient = HttpClient.create(connectionProvider)
                .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.getTrustedX509CertificatesForTrustManager().length > 0
                || ssl.isUseInsecureTrustManager()) {
            httpClient = httpClient.secure(sslContextSpec -> {
                // configure ssl
                SslContextBuilder sslContextBuilder = SslContextBuilder.forClient();

                X509Certificate[] trustedX509Certificates = ssl
                        .getTrustedX509CertificatesForTrustManager();
                if (trustedX509Certificates.length > 0) {
                    sslContextBuilder.trustManager(trustedX509Certificates);
                }
                else if (ssl.isUseInsecureTrustManager()) {
                    sslContextBuilder
                            .trustManager(InsecureTrustManagerFactory.INSTANCE);
                }


                sslContextSpec.sslContext(sslContextBuilder)
                        .defaultConfiguration(ssl.getDefaultConfigurationType())
                        .handshakeTimeout(ssl.getHandshakeTimeout())
                        .closeNotifyFlushTimeout(ssl.getCloseNotifyFlushTimeout())
                        .closeNotifyReadTimeout(ssl.getCloseNotifyReadTimeout())
                        .handlerConfigurator(
                                (handler)->{
                                    SSLEngine engine = handler.engine();
                                    //engine.setNeedClientAuth(true);
                                    SSLParameters params = new SSLParameters();
                                    List<SNIMatcher> matchers = new LinkedList<>();
                                    SNIMatcher matcher = new SNIMatcher(0) {

                                        @Override
                                        public boolean matches(SNIServerName serverName) {
                                            return true;
                                        }
                                    };
                                    matchers.add(matcher);
                                    params.setSNIMatchers(matchers);
                                    engine.setSSLParameters(params);
                                }
                        )
                ;
            });
        }

        return httpClient;

    }

以上代码段使用handlerConfigurator类中存在的netty's Builder提供的SslProvider自定义SslHandler,以避免主机名匹配。