HttpsUrlConnection不会调用set SSLSocketFactory的createSocket

时间:2016-02-22 10:30:14

标签: java android sockets ssl httpurlconnection

我目前正在开发一个Android应用程序,其中执行一些https调用(我使用客户端证书)。

这是我的代码:

// We create the client PKCS12 certificate
final KeyStore clientCertificateKeyStore = KeyStore.getInstance("PKCS12");
try
{
  clientCertificateKeyStore.load(this.clientCertificatePayload, this.clientCertificatePassword.toCharArray());
}
finally
{
  this.clientCertificatePayload.close();
}

final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
keyManagerFactory.init(clientCertificateKeyStore, clientCertificatePassword.toCharArray());

final KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, null, null);

final URL url = new URL("https://myuri.com");
final HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(sslContext.getSocketFactory());
httpURLConnection.setReadTimeout(getReadTimeout());
httpURLConnection.setConnectTimeout(getConnectTimeout());
httpURLConnection.setDoInput(true);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);

final OutputStream outputStream = httpURLConnection.getOutputStream();
final BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
bufferedWriter.write(body);
bufferedWriter.flush();
bufferedWriter.close();
outputStream.close();

httpURLConnection.connect();
//...

此代码在我的Android版Nexus 5上完美运行,但在使用Android 4.2.2的Wiko Rainbow上无效。实际上,在将sslSocketFactory设置为我的httpURLConnection之后,当我调用getOutputStream方法时,我有以下异常:

Caused by: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x631b60c8: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x59b4c8a8:0x00000000)
   at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:421)
   at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
   at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:486)
   at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:450)
   at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
   at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
   at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81)
   at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:205)
   at libcore.net.http.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:281)
   at com.splunk.mint.network.http.MonitorableHttpsURLConnection.getOutputStream(MonitorableHttpsURLConnection.java:93)
   at com.smartnsoft.droid4me.ws.URLConnectionWebServiceCaller.performHttpRequest(URLConnectionWebServiceCaller.java:472)
   at com.smartnsoft.droid4me.ws.URLConnectionWebServiceCaller.performHttpRequest(URLConnectionWebServiceCaller.java:562)
   at com.smartnsoft.droid4me.ws.URLConnectionWebServiceCaller.getInputStream(URLConnectionWebServiceCaller.java:158)
    ... 14 more
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x631b60c8: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x59b4c8a8:0x00000000)
   at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHand

我在互联网上读到,我必须强制使用TLS协议并删除SSLv3协议。为此,我发现了很多代码示例,包括this onethis one

所以,我已经更新了我的代码:

if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP)
{
  sslContext = SSLContext.getInstance("TLS");
  sslContext.init(keyManagers, null, null);
  ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(sslContext.getSocketFactory());
}
else
{
  sslSocketFactoryEx = new SSLSocketFactoryEx(keyManagers, null, null);
  ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(sslSocketFactoryEx);
}

但是当我处于调试模式时,调试器永远不会停留在createSocket方法中。我只是觉得HttpsUrlConnection没有使用我设置的工厂来创建套接字......

我是否错过了实施中的一个步骤?

感谢您的帮助!

0 个答案:

没有答案