我正在尝试进行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)
这是工作示例:
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());
}
}
}
3 回答
弄清楚了 . 我绊倒鞋带的两个地方是:
需要使用PoolingHttpClientConnectionManager注册https
将TLSv1设置为SSLConnectionSocketFactory中唯一受支持的协议
看起来你正在连接到服务器,在这个时代,它仍然支持SSLv2 .
尝试从启用的协议列表中删除
SSlv2ClientHello
,但是您可以使用Apache HTTPClient执行此操作 .NB你自2004年以来就没有需要
com.sun.net.ssl.internal.ssl.Provider
那些东西了,你需要知道你的TrustManager
和HostnameVerifier
都是根本不安全的 . 另外TrustManager.getAcceptedIssuers()
不允许返回null:请参阅Javadoc .似乎问题是JDK8客户端无法使用默认Provider连接到SSL2服务器(SSLv2已被弃用很长时间) . 您必须强制服务器使用SSL3(或其他更安全的协议),或者您必须使用其他提供程序(BouncyCastle?) . 目前我们在SOAP webservice JDK8客户端和JDK6服务器上遇到了类似的问题 .
http://en.wikipedia.org/wiki/Transport_Layer_Security#SSL_2.0
http://tools.ietf.org/html/rfc6176