简体   繁体   中英

java.net.SocketException: Software caused connection abort: recv failed when using different jre security

I am getting the following exception while trying to connect to a web service using HttpsURLConnection running on a host in the same network.Firewall is off. Interesting part is that if I run the following code through my default java JRE 1.7 environment in eclipse, everything works fine.

But if I use these functions in a product code which has its own jre folder, it throws the following exception -

Caused by: java.net.SocketException: Software caused connection abort: recv failed
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:173)
    at java.net.SocketInputStream.read(SocketInputStream.java:122)
    at com.rsa.sslj.x.aP.c(Unknown Source)
    at com.rsa.sslj.x.aP.a(Unknown Source)
    at com.rsa.sslj.x.aP.a(Unknown Source)
    at com.rsa.sslj.x.aP.h(Unknown Source)
    at com.rsa.sslj.x.cy.startHandshake(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1300)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)

I noticed that the list of security providers is different in the java.security file.

Here's that list -

security.provider.1=com.rsa.jsafe.provider.JsafeJCE
security.provider.2=com.rsa.jsse.JsseProvider
security.provider.3=sun.security.provider.Sun
security.provider.4=sun.security.rsa.SunRsaSign
security.provider.5=com.sun.net.ssl.internal.ssl.Provider
security.provider.6=com.sun.crypto.provider.SunJCE
security.provider.7=sun.security.jgss.SunProvider
security.provider.8=com.sun.security.sasl.Provider
security.provider.9=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.10=sun.security.smartcardio.SunPCSC
security.provider.11=sun.security.mscapi.SunMSCAPI

These are my functions -

private InputStream Get(URL url,String keyStoreString, String keyStorePassword) {
    SSLSocketFactory sslFactory;
    try {
        sslFactory = getSSLSocketFactory(keyStoreString, keyStorePassword);     
        javax.net.ssl.HttpsURLConnection
                .setDefaultHostnameVerifier(new  javax.net.ssl.HostnameVerifier() {
                    public boolean verify(String hostname,
                            javax.net.ssl.SSLSession sslSession) {
                        if (hostname.equals("vmm")) {
                            return true;
                        }
                        return false;
                    }
                });
        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
        con.setSSLSocketFactory(sslFactory);
        con.setRequestMethod("GET");
        con.setRequestProperty("Accept", "application/json");
        InputStream responseStream = con.getInputStream();
        return responseStream;
      }catch (Exception e) {
        //log errer
      }
}
private SSLSocketFactory getSSLSocketFactory(String keyStoreString,
        String password) throws KeyStoreException,
        NoSuchAlgorithmException, CertificateException, IOException,
        UnrecoverableKeyException, KeyManagementException, AzureException {
      KeyStore ks = getKeyStore(keyStoreString, password);
      KeyManagerFactory keyManagerFactory = KeyManagerFactory
            .getInstance("SunX509");
      keyManagerFactory.init(ks, password.toCharArray());
      // Trustmanager which trusts all certificate. Not a good idea in
      // production code.
      final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        @Override
        public void checkClientTrusted(final X509Certificate[] chain,
                final String authType) {
        }

        @Override
        public void checkServerTrusted(final X509Certificate[] chain,
                final String authType) {
        }

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

    SSLContext context = SSLContext.getInstance("TLS");
    context.init(keyManagerFactory.getKeyManagers(), trustAllCerts,
            new SecureRandom());

    return context.getSocketFactory();
}

I need to get these functions working in the product code. Any help will be appreciated. Thanks in advance !!

It's possible that trying to use a SunX509 KeyManagerFactory might cause confusion with other factories behind the scenes when the RSA Jsafe has higher priority than the Sun provider.

If RSA Jsafe provides its own KeyManagerFactory implementation, perhaps try with:

KeyManagerFactory keyManagerFactory = 
    KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

(Unless you really want the SunX509 KMF, using the default algorithm in your cause is generally a better choice, so as not to have to depend on specific providers. Same for TrustManagerFactories, when applicable.)

I explicitly set the providers for KeyManagerFactory and SSLContext to 'SunJSSE' and it worked !!

KeyManagerFactory keyManagerFactory = KeyManagerFactory
            .getInstance("SunX509","SunJSSE");

SSLContext context = SSLContext.getInstance("TLS","SunJSSE");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM