Java 尝试设置URLConnection时出现SSLHandshakeException

Java 尝试设置URLConnection时出现SSLHandshakeException,java,ssl,keystore,Java,Ssl,Keystore,我有以下代码: import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import java.net.URLConnection; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ss

我有以下代码:

import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;

public class TrackWrapper {
  public static void main(String[] args) throws Exception {
/*
 *  fix for
 *    Exception in thread "main" javax.net.ssl.SSLHandshakeException:
 *       sun.security.validator.ValidatorException:
 *           PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
 *               unable to find valid certification path to requested target
 */
TrustManager[] trustAllCerts = new TrustManager[] {
   new X509TrustManager() {
      public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return null;
      }

      public void checkClientTrusted(X509Certificate[] certs, String authType) {  }

      public void checkServerTrusted(X509Certificate[] certs, String authType) {  }

   }
};

SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
      return true;
    }
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
/*
 * end of the fix
 */

URL url = new URL("https://somedomain.com:1234");
URLConnection con = url.openConnection();
con.connect();

  }
}
第一部分只是一个复制粘贴的快速修复程序,用于接受我从另一个StackOverflow问题获得的每个证书(我确信这还没有完全准备好进行生产),第二部分我尝试连接到某个SSL安全站点,该站点的客户端证书位于我的密钥库中,我收到以下错误消息:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1806)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:986)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:133)
at TrackWrapper.main(TrackWrapper.java:54)
诚然,我对SSL一无所知,因此我非常感谢您提供一些关于如何解决此问题的见解和演练

经过一些尝试后,我现在得到以下错误:

Exception in thread "main" java.net.SocketException: Software caused connection abort: recv failed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293)
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:331)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:830)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1555)
at com.sun.net.ssl.internal.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:103)
at com.sun.net.ssl.internal.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:689)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHandshaker.java:985)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:904)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:238)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:925)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:133)
at TrackWrapper.main(TrackWrapper.java:54)

您是否检查过是否需要客户端证书

错误消息也可能来自服务器端


还可以使用参数
-Djavax.net.debug=all
启动客户端。在这里,您应该看到关于失败原因的更多提示。

您应该在您试图连接的服务器的密钥库中拥有正确的SSL证书。检查这些例子。这些对我有用


您可以从浏览器导出该服务器证书(如果可以访问),也可以通过其他方式通过internet获取证书。您的证书应该匹配。一旦获得证书,就可以使用任何工具创建密钥库。或者,您可以从创建密钥库。

如何添加这些参数?我对Java开发相当陌生。另外,我需要一个通过keytool实现的客户机证书(或者我认为是这样)。当通过命令行调用
java
时,可以将命名参数添加到命令行。我不知道你是否需要客户证书以及如何获得客户证书。这取决于您尝试连接到的服务器。嘿,是的,我已经添加了客户端证书,并且刚刚开始使用您附加的参数运行我的程序。我确实看到了很多关于SSL握手的信息,显然现在我遇到了一个不同的错误,我用新的输出更新了我的问题。现在看起来主机正在关闭连接。如果没有来自SSL调试输出的信息,现在很难进一步提供帮助。您在哪个应用程序服务器上运行此功能,在哪个IDE上运行此功能?