我正在尝试调用 REST API,但出现以下异常(最后是 Complete StackTrace):
"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"
我向 API 提供者询问了这个问题,并说您使用的 SSL 库有问题。
你将如何解决这个问题?使用相同的代码(如下),我确实毫无问题地调用了 NIMBLE API REST,但在这种情况下它不起作用。然后,我没有任何文件证书(.cer)。
我需要停用 SSL 验证,因为安全方法是我已经拥有的 API KEY。
有什么建议么?
非常感谢!
==== 控制台:====
POST https://api.nexalogy.com/project/create?api_key=XXXXXXXXXXXXXXXXXXXX
HTTP Header:"Content-Type" "application/json"
HTTP Body:[{"name":"project1","lang":"en","type":"twitter"}]
api_key:XXXXXXXXXXXXXXXXXXXX
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
我也尝试了以下形式,例外是相同的:
POST https://api.nexalogy.com/project/create
HTTP Header:"Content-Type" "application/json"
HTTP Header:"api_key" "XXXXXXXXXXXXXXXXXXXX"
HTTP Body:[{"name":"project1","lang":"en","type":"twitter"}]
api_key:XXXXXXXXXXXXXXXXXXXX
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
==== 代码:====
package servlet;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/AddProject")
public class AddProject extends HttpServlet {
private static final long serialVersionUID = 1L;
public AddProject() {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String body="[{\"name\":\"project1\",\"lang\":\"en\",\"type\":\"twitter\"}]";
String api_key="XXXXXXXXXXXXXXXXXXXX";
String str_response="";
String line="";
URL url = new URL("https://api.nexalogy.com/project/create?api_key="+api_key);
try{
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type","application/json");
System.out.println("POST https://api.nexalogy.com/project/create?api_key="+api_key);
System.out.println("HTTP Header:"+"\"Content-Type\" \"application/json\"");
System.out.println("HTTP Body:"+body);
System.out.println("api_key:"+api_key);
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(body);
wr.flush();
wr.close();
InputStream is = connection.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader rd = new BufferedReader(isr);
while ((line = rd.readLine()) != null) str_response+= line + '\r';
rd.close();
System.out.println("str_response:"+str_response);
}catch(Exception e){
e.printStackTrace(System.out);
//throw new RuntimeException(e);
}
}
}
==== 完成 StackTrace:====
com.sun.jersey.api.client.ClientHandlerException: 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.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:131)
at com.sun.jersey.api.client.Client.handle(Client.java:616)
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:559)
at com.sun.jersey.api.client.WebResource.post(WebResource.java:230)
at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.tREST_2Process(Twitter_api_create_project.java:955)
at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.tJava_1Process(Twitter_api_create_project.java:635)
at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.runJobInTOS(Twitter_api_create_project.java:1641)
at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.main(Twitter_api_create_project.java:1494)
Caused by: 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(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at com.sun.net.ssl.internal.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.getOutputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
at com.sun.jersey.client.urlconnection.URLConnectionClientHandler$1$1.getOutputStream(URLConnectionClientHandler.java:203)
at com.sun.jersey.api.client.CommittingOutputStream.commitWrite(CommittingOutputStream.java:117)
at com.sun.jersey.api.client.CommittingOutputStream.write(CommittingOutputStream.java:89)
at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
at sun.nio.cs.StreamEncoder.implFlush(Unknown Source)
at sun.nio.cs.StreamEncoder.flush(Unknown Source)
at java.io.OutputStreamWriter.flush(Unknown Source)
at java.io.BufferedWriter.flush(Unknown Source)
at com.sun.jersey.core.util.ReaderWriter.writeToAsString(ReaderWriter.java:191)
at com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider.writeToAsString(AbstractMessageReaderWriterProvider.java:128)
at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:88)
at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:58)
at com.sun.jersey.api.client.TerminatingClientHandler.writeRequestEntity(TerminatingClientHandler.java:305)
at com.sun.jersey.client.urlconnection.URLConnectionClientHandler._invoke(URLConnectionClientHandler.java:182)
at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:129)
... 7 more
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 com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
... 35 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
at java.security.cert.CertPathBuilder.build(Unknown Source)
... 41 more
已编辑 2013-06-13 解决方案:实现 X509TrustManager
添加以下代码...
HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
if (connection instanceof HttpsURLConnection) {
try {
KeyManager[] km = null;
TrustManager[] tm = {new RelaxedX509TrustManager()};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, tm, new java.security.SecureRandom());
SSLSocketFactory sf = sslContext.getSocketFactory();
((HttpsURLConnection)connection).setSSLSocketFactory(sf);
System.out.println("setSSLSocketFactory OK!");
}catch (java.security.GeneralSecurityException e) {
System.out.println("GeneralSecurityException: "+e.getMessage());
}
}
...并添加以下类(实现 X509TrustManager)
class RelaxedX509TrustManager implements X509TrustManager {
public boolean isClientTrusted(java.security.cert.X509Certificate[] chain){ return true; }
public boolean isServerTrusted(java.security.cert.X509Certificate[] chain){ return true; }
public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String input) {}
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String input) {}
}