我在每次调用我的 Java 程序时都会遇到这个异常:
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
我在 OpenSuSE Linux 机器上运行 Java 1.5.0_15。我已经从 VeriSign 网站下载了根证书并使用 keytool 导入了它们。
该代码没有任何异常 - 只需发送几个参数并读取响应。代码在这篇文章的最后。
看起来我没有安装必需的证书,但我真的不明白为什么我在每次调用时都会看到这个问题!?
我使用了 -Djavax.net.debug=ssl 并获得了工作调用和失败调用的输出。前几百行的输出是相同的,然后我从失败的调用中得到这个输出:
***
main, SEND TLSv1 ALERT: fatal, description = certificate_unknown
main, WRITE: TLSv1 Alert, length = 2
main, called closeSocket()
main, handling exception: 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
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
...
%% No cached client session
*** ClientHello, TLSv1
由于 -Djavax.net.debug=ssl 属性生成的完整输出太多,无法包含在这篇文章中。
这是我正在使用的测试程序:
<imports go here>
public class HttpPoster
{
public static final String s_target = "https://<url goes here>";
private static final String s_parameters = "a=100&b=200";
public void runTest()
{
HttpURLConnection connection = createHttpConnection(s_target);
String response = null;
int statusCode = -1;
String responseMessage = null;
try
{
response = sendRequest(connection, s_parameters);
statusCode = connection.getResponseCode();
responseMessage = connection.getResponseMessage();
System.out.println("Response = " +response);
System.out.println("Status Code = " +statusCode);
System.out.println("Response Message = " +responseMessage);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (connection != null)
{
connection.disconnect();
connection = null;
}
}
}
private String sendRequest(HttpURLConnection connection, String parameters)
{
StringBuffer buffer = new StringBuffer();
try
{
// Calling getOutputStream() does an implicit connect()
OutputStreamWriter outputWriter = new OutputStreamWriter(connection.getOutputStream());
outputWriter.write(parameters);
outputWriter.flush();
// Get the response
String line = null;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while((line = bufferedReader.readLine()) != null)
{
buffer.append(line);
}
if (outputWriter != null) {
outputWriter.close();
}
if (bufferedReader != null) {
bufferedReader.close();
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
return buffer.toString();
}
private HttpURLConnection createHttpConnection(String url)
{
HttpURLConnection connection = null;
try
{
connection = (HttpURLConnection)(new URL(url)).openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestMethod("POST");
connection.setReadTimeout(15000);
setHostNameVerifier(connection);
}
catch (MalformedURLException murlException)
{
murlException.printStackTrace();
}
catch (IOException ioException)
{
ioException.printStackTrace();
}
return connection;
}
private void setHostNameVerifier(HttpURLConnection c)
{
HostnameVerifier hv = null;
if (c instanceof HttpsURLConnection)
{
hv = new HostnameVerifier()
{
public boolean verify(String urlHostName, SSLSession session)
{
// Ignore the domain mismatch
return true;
}
};
((HttpsURLConnection)c).setHostnameVerifier(hv);
}
}
public static void main(String[] args)
{
new HttpPoster().runTest();
}
}
谢谢,
保罗