javax.net.ssl.SSLException:SSL握手中止在调用webservice Android时由对等方重置连接

时间:2013-12-23 10:19:03

标签: java android web-services ssl https

我正在调用 https webservice ,之前它的工作正常,但现在当我试图调用它时,它会给我以下错误。

记录错误:

12-23 06:28:11.969: W/System.err(3014): javax.net.ssl.SSLException: SSL handshake aborted: ssl=0x1cc160: I/O error during system call, Connection reset by peer
12-23 06:28:11.979: W/System.err(3014):     at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
12-23 06:28:11.979: W/System.err(3014):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:474)
12-23 06:28:11.979: W/System.err(3014):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.<init>(OpenSSLSocketImpl.java:750)
12-23 06:28:11.979: W/System.err(3014):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:692)
12-23 06:28:11.979: W/System.err(3014):     at crittercism.android.aa.getInputStream(Unknown Source)
12-23 06:28:11.979: W/System.err(3014):     at org.apache.http.impl.io.SocketInputBuffer.<init>(SocketInputBuffer.java:93)
12-23 06:28:11.979: W/System.err(3014):     at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83)
12-23 06:28:11.979: W/System.err(3014):     at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170)
12-23 06:28:11.979: W/System.err(3014):     at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106)
12-23 06:28:11.979: W/System.err(3014):     at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129)
12-23 06:28:11.979: W/System.err(3014):     at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:171)
12-23 06:28:11.989: W/System.err(3014):     at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
12-23 06:28:11.989: W/System.err(3014):     at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
12-23 06:28:11.989: W/System.err(3014):     at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:359)
12-23 06:28:11.989: W/System.err(3014):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
12-23 06:28:11.989: W/System.err(3014):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
12-23 06:28:11.989: W/System.err(3014):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)

我使用以下代码来调用https webservice。

public static void trustAllHosts() {

        X509TrustManager easyTrustManager = new X509TrustManager() {

            public void checkClientTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
                // Oh, I am easy!
            }

            public void checkServerTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
                // Oh, I am easy!
            }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }

        };

        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { easyTrustManager };

        // Install the all-trusting trust manager
        try {
            SSLContext sc = SSLContext.getInstance("TLS");

            sc.init(null, trustAllCerts, new java.security.SecureRandom());

            HttpsURLConnection
                    .setDefaultSSLSocketFactory(sc.getSocketFactory());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static HttpClient getNewHttpClient() {
        try {
            KeyStore trustStore = KeyStore.getInstance(KeyStore
                    .getDefaultType());
            trustStore.load(null, null);

            SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            HttpParams params = new BasicHttpParams();
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

            SchemeRegistry registry = new SchemeRegistry();
            registry.register(new Scheme("http", PlainSocketFactory
                    .getSocketFactory(), 80));
            registry.register(new Scheme("https", sf, 443));

            ClientConnectionManager ccm = new ThreadSafeClientConnManager(
                    params, registry);

            return new DefaultHttpClient(ccm, params);
        } catch (Exception e) {
            return new DefaultHttpClient();
        }
    }

MySSLSocketFactory.java

public class MySSLSocketFactory extends SSLSocketFactory {
    SSLContext sslContext = SSLContext.getInstance("TLS");

    public MySSLSocketFactory(KeyStore truststore)
            throws NoSuchAlgorithmException, KeyManagementException,
            KeyStoreException, UnrecoverableKeyException {
        super(truststore);

        TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
            }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        sslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port,
            boolean autoClose) throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, host, port,
                autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
}

以前工作正常,但现在失败了。服务器中没有任何更改。

我已提到

  1. Android-Query - Random SSLExceptions
  2. Intermittent Connection Reset by Peer errors in Android connecting to .NET REST endpoint
  3. Android HTTPS exception Connection reset by peer
  4. Why is HttpUrlConnection throwing an SSLException while on a mobile data connection?
  5. 我已经在wifi和移动数据中测试了它。应用程序不兼容。

    如果有人在此之前遇到此问题,请帮我解决。

4 个答案:

答案 0 :(得分:28)

我也有同样的例外。我发现它是由于服务器不支持 TLS 1.0协议

我发现Android设备http连接无法访问不支持TLS 1.0的服务器。我搜索了关于这个bug的每个地方,但没有发现任何与此问题有关的内容。当TLS 1.0 protocol支持添加到服务器时,问题就解决了。您可以使用https://www.ssllabs.com/ssltest检查服务器/主机名协议支持。

答案 1 :(得分:3)

可能有两个原因:

证书可能在客户端或服务器端过期。

解决方案: 延长现有证书的到期日或更换新证书。

服务器端口已重置为其他端口。

解决方案: 我遇到过这个端口更改问题,通常是由于服务器维护或补丁更新,有时服务端口会发生变化。询问为您提供wsdl的人在其服务器上重新生成wsdl,并检查端口号是否与客户端的现有wsdl匹配。很可能这就是这种情况。

答案 2 :(得分:2)

今天早上我们遇到了同样的问题并得到了解决。

IIS 8上的SSL

  1. 昨天晚上工作正常,昨晚我们的SSL在IIS网站上更新了。
  2. 在检查站点Bindings到SSL时,我们注意到IIS8有一个新的复选框“需要服务器名称指示”,它没有被检查,所以我们继续启用它。
  3. 引发了这个问题。
  4. 回到IIS,禁用了复选框....问题解决了!

答案 3 :(得分:1)

我对某些Android设备遇到了同样的问题。通过 IIS服务器设置找到解决方案。

<强>步骤:

  1. 打开IIS
  2. 选择您正在使用的网站
  3. 修改网站绑定
  4. 取消选中所需的服务器名称标识
  5. 点击确定
  6. 参考屏幕截图:

    enter image description here

    希望这会对你有所帮助。