java - 不支持的记录版本 SSLv2Hello 使用 CloseableHttpClient

标签 java ssl apache-httpcomponents

我正在尝试进行 https 调用并收到以下错误: 不支持的记录版本 SSLv2Hello

任何人都可以阐明我做错了什么吗? 感谢您的帮助。

这是 StackTrace:

debug:
Unsupported record version SSLv2Hello
javax.net.ssl.SSLException: Unsupported record version SSLv2Hello
at sun.security.ssl.InputRecord.readV3Record(Unknown Source)
at sun.security.ssl.InputRecord.read(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:275)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:254)
at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:123)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:318)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at httpcomponents.httpsTest.main(httpsTest.java:135)

Here is working example:

import com.sun.net.ssl.internal.ssl.Provider;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;    
String audioURL = "https://mydata.com/webreports/audio.jsp?callID=338786512&authentication=98695279578B04166629C0";
RequestConfig requestConfig = null;
    requestConfig = RequestConfig
        .custom()
        .setConnectTimeout(5000)
        .setConnectionRequestTimeout(5000)
        .setSocketTimeout(5000)
        .build();
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = null;
poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
poolingHttpClientConnectionManager.setMaxTotal(5);
CloseableHttpClient closeableHttpClient = null;
HttpHead httpHead = new HttpHead(audioURL);
try {
    Provider sslProvider = new Provider();
    if (Security.getProvider(sslProvider.getName()) == null) {
        Security.addProvider(sslProvider);
    }
    TrustManager[] trustAllCerts = new TrustManager[]{
        new X509TrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            @Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
            }
            @Override
            public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
            }
        }
    };
    SSLContext sslContext = SSLContexts
            .custom()
            .useSSL()
            .build();
    sslContext.init(null, trustAllCerts, new SecureRandom());
    LayeredConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);
    X509HostnameVerifier x509HostnameVerifier = new X509HostnameVerifier() {
        @Override
        public void verify(String host, SSLSocket ssl) throws IOException {
            //do nothing
        }
        @Override
        public void verify(String host, X509Certificate cert) throws SSLException {
            //do nothing                                                            //do nothing
        }
        @Override
        public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
            //do nothing
        }
        @Override
        public boolean verify(String string, SSLSession ssls) {
            return true;
        }
    };
    closeableHttpClient = HttpClientBuilder
            .create()
            .setDefaultRequestConfig(requestConfig)
            .setConnectionManager(poolingHttpClientConnectionManager)
            .setSslcontext(sslContext)
            .setHostnameVerifier(x509HostnameVerifier)
            .setSSLSocketFactory(sslConnectionSocketFactory)
            .build();
} catch (NoSuchAlgorithmException noSuchAlgorithmException) {
    System.out.println(noSuchAlgorithmException.getMessage());
} catch (KeyManagementException keyManagementException) {
    System.out.println(keyManagementException.getMessage());
}
HttpContext httpContext = new BasicHttpContext();
CloseableHttpResponse closeableHttpResponse = null;
try {
    if (closeableHttpClient != null) {
        closeableHttpResponse = closeableHttpClient.execute(httpHead, httpContext);
        if (closeableHttpResponse != null) {
            int statusCode = closeableHttpResponse.getStatusLine().getStatusCode();
            System.out.println(String.valueOf(statusCode));
        }
    }
} catch (IOException iOException) {
    System.out.println(iOException.getMessage());
} finally {
    if (closeableHttpResponse != null) {
        try {
            closeableHttpResponse.close();
        } catch (IOException iOException) {
            System.out.println(iOException.getMessage());
        }
    }
    if (closeableHttpClient != null) {
        try {
            closeableHttpClient.close();
        } catch (IOException iOException) {
            System.out.println(iOException.getMessage());
        }
    }
}

最佳答案

问题似乎是 JDK8 客户端无法使用默认提供程序连接到 SSL2 服务器(SSLv2 已被弃用很长时间)。您必须强制服务器使用 SSL3(或其他更安全的协议(protocol)),或者您必须使用其他提供商(BouncyCaSTLe?)。 目前我们在 SOAP web 服务 JDK8 客户端和 JDK6 服务器上有类似的问题。

http://en.wikipedia.org/wiki/Transport_Layer_Security#SSL_2.0

https://www.rfc-editor.org/rfc/rfc6176

关于java - 不支持的记录版本 SSLv2Hello 使用 CloseableHttpClient,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26166121/

相关文章:

java - 简单的 Java OpenGL 纹理管理器

java - NIO 聊天应用程序无法为多个客户端正常工作

linux - nginx force SSL no-www 重定向问题

c - EAP-TLS 的 s_client 实现代码

http - 如何在 Artifactory 中禁用 HTTP

java - 池化 HttpClientConnectionManager : How to do Https requests?

java - 为什么我的 HttpClient 类卡住某些 URL

java - 创建 keystore 并将证书附加到其中后, keystore 格式无效

java - 将 Maven 插件绑定(bind)到编译阶段时出现问题

java - Apache Commons HttpComponents 示例