我有一个基于java的自定义工具来ping指定端口上的服务器。该工具在Windows 7 x86上运行正常,但在使用Java x64的Windows 7 x64上出现以下错误时失败:
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
以下是一些细节:
首先,为了ping这个服务器,我保存了它的CA证书。为此,我使用了以下工具: https://github.com/escline/InstallCert/blob/master/InstallCert.java
此工具的结果是jssecacerts文件。我将此文件放在C:\ Program Files \ Java \ jre1.8.0_77 \ lib \ security中 定义了JAVA_HOME变量:C:\ Program Files \ Java \ jre1.8.0_77
然后,我使用我的工具ping服务器:
package CallNotificationService;
import java.net.*;
import java.io.*;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.security.SecureRandom;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
public class CallNotificationService {
public static void main(String[] args) throws Exception
{
String MyServ = args[0];
String certificate = args[1];
String certPassword = args[2];
System.out.println(MyServ + " " + certificate + " " + certPassword);
String notificationService = "https://" + MyServ + ":9443/available";
URL url = new URL(notificationService);
HostnameVerifier HostValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(HostValid);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setSSLSocketFactory(getFactory(new File(certificate), certPassword));
BufferedReader intpam = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = intpam.readLine()) != null) {
response.append(inputLine);
}
intpam.close();
System.out.println(response.toString());
}
public static SSLSocketFactory getFactory( File pKeyFile, String pKeyPassword ) throws Exception {
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
InputStream keyInput = new FileInputStream(pKeyFile);
keyStore.load(keyInput, pKeyPassword.toCharArray());
keyInput.close();
keyManagerFactory.init(keyStore, pKeyPassword.toCharArray());
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
return context.getSocketFactory();
}
}
在stderr中,我有以下内容:
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
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
at sun.security.ssl.Handshaker.processLoop(Unknown Source)
at sun.security.ssl.Handshaker.process_record(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
at CallNotificationService.CallNotificationService.main(CallNotificationService.java:48)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
at sun.security.validator.Validator.validate(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
... 14 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(Unknown Source)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
at java.security.cert.CertPathBuilder.build(Unknown Source)
... 20 more
我还尝试按照文档(https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/properties.html)将jssecacerts放到%USER_HOME \ security \ trusted.jssecacerts,但它没有帮助。
注意:如果我在命令行中指定-Djavax.net.ssl.trustStore = jssecacerts,则 DOES 有效(在这种情况下,jssecacerts放置在与我的jar应用程序相同的文件夹。)
问题:,因为此代码在x86中有效,我想x64中的这个失败可能与jssecacerts位置或类似的东西有关。 我应该尝试解决此问题? x64中是否有特定的jssecacerts位置?
谢谢, 浣熊