我有一个用 Java 编写的 RESTful 客户端,用于使用 SSL 的 Web 服务。该应用程序已经运行了好几个星期。突然之间,所有与 Web 服务进行交易的尝试都会导致以下异常:
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
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 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1699)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1206)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136)
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:893)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149)
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.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
at com.MSCA.ESP.WebApp.ABSManager.getFacilityMetrics(ABSManager.java:1000)
....
我发现的关于类似困难的信息,比如这个,似乎表明我需要在我的客户端环境中使用由/用于 Web 服务的证书做一些事情。但是,我继续能够在 Firefox 中使用 RESTclient 执行在我的 Java 客户端中失败的相同事务,并且据我所知,我从未向 RESTclient 提供与该服务相关的任何类型的证书。
这个应用程序的背景故事是 Web 服务最初是基于 SOAP 协议的,并且最近更改为 REST,这增加了另一个级别的复杂性和混乱,至少从我的角度来看,尽管这可能是其他人的线索至于我的问题可能是什么。最重要的是,我记得几年前第一次开发应用程序时处理 SSL 的唯一一件事是我必须向其中添加以下代码:
static
{
Security.addProvider( new com.sun.net.ssl.internal.ssl.Provider() );
System.setProperty( "java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol" );
System.setProperty( "javax.net.ssl.trustStore", "./Resources/client.keystore" );
}
client.keystore 文件最初是随 SOAP 接口的示例客户端代码一起提供的。一旦服务切换到 REST,我就保留了这段代码和 client.keystore 文件,因为它似乎没有引起问题,即使似乎没有向严格编写 RESTful 客户端的开发人员提供 client.keystore对于新服务。我今天向 Web 服务提供商提交了一个支持请求,询问可能需要更新 client.keystore。我的困难似乎并没有与他们敲响警钟,所以我想也许我在那里叫错了树。
我不知道我是否在这里提供了足够的信息让任何人给我一个完整的答案,但在这一点上,我很乐意只追求一个特定的向量。到目前为止,我似乎在兜圈子。最后,我不知道这是否重要,但我的应用程序在 Windows Server 2003 标准版上的 Glassfish 3.1.1 下运行。