我想访问一个SOAP webservice url,其中https托管在远程虚拟机中.我在使用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
尝试了谷歌搜索的不同解决方案,非他们的工作.我想避免使用keytool,因为我将在不同的vm上运行我的测试.
有人有任何解决方案吗?
解决方法
使用X509ExtendedTrustManager而不是X509TrustManager()解决了这个问题.这是一个例子:
public void trustAllHosts() { try { TrustManager[] trustAllCerts = new TrustManager[]{ new X509ExtendedTrustManager() { @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted(java.security.cert.X509Certificate[] certs,String authType) { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] certs,String authType) { } @Override public void checkClientTrusted(java.security.cert.X509Certificate[] xcs,String string,Socket socket) throws CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] xcs,Socket socket) throws CertificateException { } @Override public void checkClientTrusted(java.security.cert.X509Certificate[] xcs,SSLEngine ssle) throws CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] xcs,SSLEngine ssle) throws CertificateException { } } }; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null,new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // Create all-trusting host name verifier HostnameVerifier allHostsValid = new HostnameVerifier() { @Override public boolean verify(String hostname,SSLSession session) { return true; } }; // Install the all-trusting host verifier HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); } catch (Exception e) { log.error("Error occurred",e); } }