アクセスしたいSOAPリモートVMでhttpsがホストされているWebサービスURL。HttpURLConnectionを使用してアクセスしているときに例外が発生します。
これが私のコードです:
import javax.net.ssl.*;
import Java.io.OutputStream;
import Java.net.HttpURLConnection;
import Java.net.URL;
import Java.security.cert.CertificateException;
import Java.security.cert.X509Certificate;
/**
* Created by prasantabiswas on 07/03/17.
*/
public class Main
{
public static void main(String [] args)
{
try
{
URL url = new URL("https://myhost:8913/myservice/service?wsdl");
HttpURLConnection http = null;
if (url.getProtocol().toLowerCase().equals("https")) {
trustAllHosts();
HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
https.setHostnameVerifier(DO_NOT_VERIFY);
http = https;
} else {
http = (HttpURLConnection) url.openConnection();
}
String SOAPAction="";
// http.setRequestProperty("Content-Length", String.valueOf(b.length));
http.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
http.setRequestProperty("SOAPAction", SOAPAction);
http.setRequestMethod("GET");
http.setDoOutput(true);
http.setDoInput(true);
OutputStream out = http.getOutputStream();
}
catch (Exception e)
{
e.printStackTrace();
}
}
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
private static void trustAllHosts() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public Java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new Java.security.cert.X509Certificate[] {};
}
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException
{
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
} };
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new Java.security.SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
}
次の例外が発生します。
javax.net.ssl.SSLHandshakeException: Java.security.cert.CertificateException: Certificates does not conform to algorithm constraints
at Sun.security.ssl.Alerts.getSSLException(Alerts.Java:192)
at Sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.Java:1949)
at Sun.security.ssl.Handshaker.fatalSE(Handshaker.Java:302)
at Sun.security.ssl.Handshaker.fatalSE(Handshaker.Java:296)
at Sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.Java:1509)
at Sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.Java:216)
at Sun.security.ssl.Handshaker.processLoop(Handshaker.Java:979)
at Sun.security.ssl.Handshaker.process_record(Handshaker.Java:914)
at Sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.Java:1062)
at Sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.Java:1375)
at Sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.Java:1403)
at Sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.Java:1387)
at Sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.Java:559)
at Sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.Java:185)
at Sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.Java:1283)
at Sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.Java:1258)
at Sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.Java:250)
at Main.main(Main.Java:35)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:62)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
at Java.lang.reflect.Method.invoke(Method.Java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.Java:147)
Caused by: Java.security.cert.CertificateException: Certificates does not conform to algorithm constraints
at Sun.security.ssl.AbstractTrustManagerWrapper.checkAlgorithmConstraints(SSLContextImpl.Java:1055)
at Sun.security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(SSLContextImpl.Java:981)
at Sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.Java:923)
at Sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.Java:1491)
... 18 more
グーグル検索とは異なるソリューションを試してみましたが、それらのどれも機能しませんでした。別のvmでテストを実行するため、keytoolの使用を避けたいです。
誰かがこれに対する解決策を持っていますか?
HttpsURLConnection.setDefaultSSLSocketFactory
と独自のTrustManager
またはX509ExtendedTrustManager
の実装を使用する代わりに、TrustManagerFactory
をKeyStore
とともに使用し、証明書を発行した証明書を使用できます。信頼する必要があり(自己署名証明書の場合、これはホスト証明書と同じです)、特定のインスタンスでHttpsURLConnection.setSSLSocketFactory
を呼び出す必要があります。これはコードが少なく、すべてのHTTPS証明書を信頼することによるセキュリティの問題を回避します。
main
内:
if (url.getProtocol().toLowerCase().equals("https")) {
HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
https.setSSLSocketFactory(createSSLSocketFactory());
http = https;
}
メソッドcreateSSLSocketFactory
は次のようになります。
private static SSLSocketFactory createSSLSocketFactory() {
File crtFile = new File("server.crt");
Certificate certificate = CertificateFactory.getInstance("X.509").generateCertificate(new FileInputStream(crtFile));
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("server", certificate);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
return sslContext.getSocketFactory();
}