Java プログラムを 1 回おきに呼び出すと、次の例外が発生します。
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 Web サイトからルート証明書をダウンロードし、keytool を使用してインポートしました。
このコードは特別なことは何もしていません。いくつかのパラメーターを送信し、応答を読み取るだけです。コードはこの記事の最後にあります。
必要な証明書がインストールされていないように見えますが、2 回目の呼び出しごとにこの問題が発生する理由が本当にわかりません!?
私は -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();
}
}
ありがとう、
ポール