2014-03-31 47 views
1

在使用同一网络中的主机上运行的HttpsURLConnection尝试连接到Web服务时,出现以下异常。防火墙处于关闭状态。有趣的部分是,如果我通过Eclipse中的默认Java JRE 1.7环境运行以下代码,一切正常。java.net.SocketException:软件导致连接中止:使用不同的jre安全时,recv失败

但是,如果我有自己的JRE文件夹中的产品代码中使用这些功能,它抛出以下异常 -

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) 

我注意到安全提供者列表中java.security文件不同。

这里是一个名单 -

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 

这些都是我的功能 -

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(); 
} 

我需要这些功能的产品代码工作。任何帮助将不胜感激。提前致谢 !!

回答

0

我明确地将KeyManagerFactory和SSLContext的提供者设置为'SunJSSE'并且它工作正常!

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

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

这很有道理,但为什么要在生产环境中安装RSA JSSE提供程序并且不使用它(因为您明显在这里强制使用Oracle/Sun JSSE提供程序)?请注意,您的主机名验证者和信任管理者也不安全。 – Bruno

0

当RSA Jsafe具有比Sun提供者更高的优先级时,尝试使用SunX509KeyManagerFactory可能会导致与幕后其他工厂混淆。

如果RSA Jsafe提供了自己的KeyManagerFactory实现,也许尝试:

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

(除非你真的想SunX509 KMF,在你的事业使用默认的算法一般是一个更好的选择,以免必须要依赖于特定的提供商TrustManagerFactories适用时也是如此)

+0

试过这个。但没有帮助! –

相关问题