UrlConnection:SSLProtocolException:SSL握手中止:ssl = 0x631b60c8:SSL库失败,通常是协议错误

rol*_*ndl 5 java ssl https android urlconnection

我目前正在将Android从HttpClient迁移到UrlConnection。我至少在Android 4.2.2上遇到了一些问题。

我试图调用的URL是一个https URL,我必须使用客户端证书。

基于此博客文章,我编写了以下代码:

// 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);
Run Code Online (Sandbox Code Playgroud)

然后在我的代码中,我使用sslContext变量将SSL Factory设置为my httpURLConnection

((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(sslContext.getSocketFactory()); 
Run Code Online (Sandbox Code Playgroud)

这段代码可在Android 6.0.1的Nexus 5上完美运行,但在Android 4.2.2的Wiko Rainbow上则无法运行。实际上,将sslSocketFactory设置为my之后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
Run Code Online (Sandbox Code Playgroud)

我尝试了几种解决方案,包括这一解决方案,但仍然有例外。

您是否知道如何使代码在Android 4.2.2上运行?

谢谢您的帮助 !

编辑:在这里我用的方式NoSSLv3Factory

基本上,我使用相同的代码来创建客户端PKCS12证书并初始化SSLContext。区别在于何时将设置SSLSocketFactoryHttpUrlConnection。这是我尝试使用的条件:

if (httpURLConnection instanceof HttpsURLConnection)
{
  if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP)
  {
    ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(sslContext.getSocketFactory());
  }
  else
  {
    ((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new NoSSLv3Factory());
  }
Run Code Online (Sandbox Code Playgroud)

}

我还尝试使用以下代码使用构造函数的另一个版本:

((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(new NoSSLv3Factory(sslContext.getSocketFactory())); 
Run Code Online (Sandbox Code Playgroud)

但是我仍然有同样的例外:(