new URL(ENDPOINT).openConnection()で、ENDPOINTに「https://」プロトコルを指定すると、サーバとSSL通信ができます。
SSL通信するためには、サーバ証明書が必要なんですが、買おうとするととても高い。(無料でSSL証明書がつくれるサービスもありますが、ちょっと手間。)
なので、開発時においては、keytoolなどを利用して自分で証明書を作成したり、サーバデフォルトのSSL証明書を使ったりします。
その際、証明書が正式なものでないため、証明書認証でExceptionが発生しちゃいます。以下のようなException。
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
とか、
java.io.IOException: HTTPS hostname wrong: should be
本投稿ではそれの対処方法をご紹介します。
証明書で無視する項目は以下の2つです。
1.証明書が信用できるかをチェックしないようにする。
2.証明書とサーバのホスト名がマッチしているかチェックしないようにする。
では、以下、実装方法です。
SSLSocketFactoryを渡します。
2.HttpsURLConnection.setHostnameVerifierにサーバをチェックしないようなX509TrustManagerを渡します。
例えば、以下のようなソースです。 public static String doGET() throws Exception {
HttpsURLConnection connection = (HttpsURLConnection) new URL("https://google.com").openConnection();
connection.setSSLSocketFactory(createNoCheckSSLFactory());
connection.setHostnameVerifier(new NoCheckHostnameVerifier());
int responseCode = connection.getResponseCode();
if (200 != responseCode) {
String errorMessage = streamToString(connection.getErrorStream());
throw new IOException("status = " + responseCode + ", message = " + errorMessage);
}
return streamToString(connection.getInputStream());
}
private static SSLSocketFactory createNoCheckSSLFactory() throws Exception {
TrustManager[] trustAllCerts = new TrustManager[] { new NoCheckX509TrustManager() };
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
return sc.getSocketFactory();
}
private static class NoCheckX509TrustManager implements X509TrustManager {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}
private static class NoCheckHostnameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
0 件のコメント:
コメントを投稿