如何在JAX-WS客户端中禁用证书validation?

如何使用javax.xml.ws.Service在JAX-WS客户端中禁用证书validation?

我尝试在SSLSocketFactory中创建一个完全信任的TrustManager,并尝试将其与BindingProvider绑定

 SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); Map ctxt = ((BindingProvider) wsport ).getRequestContext(); ctxt.put(JAXWSProperties.SSL_SOCKET_FACTORY, sc.getSocketFactory()); 

但我仍然得到Exception: unable to find valid certification path to requested target

但它只在我使用时有效

 HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 

或者有没有办法让javax.xml.ws.Service使用我创建的HttpsURLConnection

我在这里找到了一个解决方案: http : //schrepfler.blogspot.com.br/2009/06/relaxing-ssl-validation-for-jaxws.html

我正在使用该解决方案在主类的静态块上调用两个静态方法,如下所示:

 static { SSLUtilities.trustAllHostnames(); SSLUtilities.trustAllHttpsCertificates(); } 

希望这可以帮助

编辑:正如David J. Liszewski指出的那样,这会破坏来自此JVM的所有连接的SSL / TLS 。 所以记住这一点。

事实可以从Erik Wramner的博客中找到http://erikwramner.wordpress.com/2013/03/27/trust-self-signed-ssl-certificates-and-skip-host-name-verification-with-jax- WS

我提供了完整的解决方案,其中Apache CXF用于向自签名的SharePoint https服务发出SOAP Web服务请求:

NaiveSSLHelper.java

 import org.apache.cxf.configuration.jsse.TLSClientParameters; import org.apache.cxf.transport.http.HTTPConduit; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.xml.ws.BindingProvider; import java.security.GeneralSecurityException; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Map; public class NaiveSSLHelper { public static void makeWebServiceClientTrustEveryone( Object webServicePort) { if (webServicePort instanceof BindingProvider) { BindingProvider bp = (BindingProvider) webServicePort; Map requestContext = bp.getRequestContext(); requestContext.put(JAXWS_SSL_SOCKET_FACTORY, getTrustingSSLSocketFactory()); requestContext.put(JAXWS_HOSTNAME_VERIFIER, new NaiveHostnameVerifier()); } else { throw new IllegalArgumentException( "Web service port " + webServicePort.getClass().getName() + " does not implement " + BindingProvider.class.getName()); } } public static SSLSocketFactory getTrustingSSLSocketFactory() { return SSLSocketFactoryHolder.INSTANCE; } private static SSLSocketFactory createSSLSocketFactory() { TrustManager[] trustManagers = new TrustManager[] { new NaiveTrustManager() }; SSLContext sslContext; try { sslContext = SSLContext.getInstance("TLS"); sslContext.init(new KeyManager[0], trustManagers, new SecureRandom()); return sslContext.getSocketFactory(); } catch (GeneralSecurityException e) { return null; } } public static void makeCxfWebServiceClientTrustEveryone(HTTPConduit http) { TrustManager[] trustManagers = new TrustManager[]{ new NaiveTrustManager() }; TLSClientParameters tlsParams = new TLSClientParameters(); tlsParams.setSecureSocketProtocol("TLS"); tlsParams.setKeyManagers(new KeyManager[0]); tlsParams.setTrustManagers(trustManagers); tlsParams.setDisableCNCheck(true); http.setTlsClientParameters(tlsParams); } private interface SSLSocketFactoryHolder { SSLSocketFactory INSTANCE = createSSLSocketFactory(); } private static class NaiveHostnameVerifier implements HostnameVerifier { @Override public boolean verify(String hostName, SSLSession session) { return true; } } private static class NaiveTrustManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } private static final java.lang.String JAXWS_HOSTNAME_VERIFIER = "com.sun.xml.internal.ws.transport.https.client.hostname.verifier"; private static final java.lang.String JAXWS_SSL_SOCKET_FACTORY = "com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory"; } 

SoapTester.java

 import crawler.common.sharepoint.stubs.sitedata.ArrayOfSList; import crawler.common.sharepoint.stubs.sitedata.GetListCollectionResponse; import crawler.common.sharepoint.stubs.sitedata.SList; import crawler.common.sharepoint.stubs.sitedata.SiteData; import crawler.common.sharepoint.stubs.sitedata.SiteDataSoap; import org.apache.cxf.configuration.security.AuthorizationPolicy; import org.apache.cxf.endpoint.Client; import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.transport.http.HTTPConduit; import org.apache.cxf.transport.http.asyncclient.AsyncHTTPConduit; import org.apache.cxf.transport.http.auth.HttpAuthHeader; import org.apache.cxf.transport.http.auth.SpnegoAuthSupplier; import org.apache.cxf.transports.http.configuration.HTTPClientPolicy; import org.ietf.jgss.GSSName; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.security.auth.login.AppConfigurationEntry; import javax.security.auth.login.Configuration; import javax.xml.namespace.QName; import javax.xml.soap.SOAPMessage; import javax.xml.ws.BindingProvider; import javax.xml.ws.Holder; import javax.xml.ws.Service; import javax.xml.ws.handler.Handler; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext; import java.io.ByteArrayOutputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * This example will invoke a web service on SharePoint 2013+ with optional kerberos auth. */ public class SoapTester { private static final Logger LOG = LoggerFactory.getLogger(SoapTester.class); public static void main(String[] args) { String endpointAddress = args[0]; String keytabFilePath = args.length > 2 ? args[1] : null; String principalName = args.length > 2 ? args[2] : null; String servicePrincipalName = args.length > 3 ? args[3] : null; if (!endpointAddress.endsWith("/")) { endpointAddress += "/"; } endpointAddress += "_vti_bin/SiteData.asmx"; final String endpointAddressFinal = endpointAddress; Service service = Service.create(SiteData.SERVICE); SiteDataSoap soap = service.getPort(SiteDataSoap.class); NaiveSSLHelper.makeWebServiceClientTrustEveryone(soap); BindingProvider bindingProvider = (BindingProvider) soap; bindingProvider.getRequestContext().put(AsyncHTTPConduit.USE_ASYNC, Boolean.TRUE); bindingProvider.getRequestContext().put( BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointAddress); List chain = bindingProvider.getBinding().getHandlerChain(); chain.add(new SOAPHandler() { @Override public boolean handleMessage(SOAPMessageContext context) { String endpointAddress = (String) context.get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY); SOAPMessage msg = context.getMessage(); Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { msg.writeTo(out); String str = new String(out.toByteArray()); LOG.info("Sharepoint xml [" + endpointAddress + "]" + (outbound ? " (Outbound)" : " (Inbound)") + ": " + str); } catch (Exception e) { LOG.error("Cannot get soap xml from message ", e); } if (outbound.booleanValue()) { try { context.getMessage().setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-8"); } catch (Exception e) { throw new RuntimeException(e); } } return true; } @Override public boolean handleFault(SOAPMessageContext context) { return true; } @Override public void close(MessageContext context) { } @Override public Set getHeaders() { return null; } }); bindingProvider.getBinding().setHandlerChain(chain); Client client = ClientProxy.getClient(bindingProvider); client.getEndpoint().put("org.apache.cxf.stax.maxChildElements", System.getProperty("org.apache.cxf.stax.maxChildElements") != null ? System.getProperty("org.apache.cxf.stax.maxChildElements") : "5000000"); HTTPConduit http = (HTTPConduit) client.getConduit(); NaiveSSLHelper.makeCxfWebServiceClientTrustEveryone(http); AuthorizationPolicy authorization = new AuthorizationPolicy(); authorization.setAuthorizationType(HttpAuthHeader.AUTH_TYPE_NEGOTIATE); http.setAuthorization(authorization); SpnegoAuthSupplier authSupplier = new SpnegoAuthSupplier(); if (servicePrincipalName != null) { authSupplier.setServicePrincipalName(servicePrincipalName); authSupplier.setServiceNameType(GSSName.NT_HOSTBASED_SERVICE); } Map loginConfig = new HashMap<>(); loginConfig.put("useKeyTab", "true"); loginConfig.put("storeKey", "true"); loginConfig.put("refreshKrb5Config", "true"); loginConfig.put("keyTab", keytabFilePath); loginConfig.put("principal", principalName); loginConfig.put("useTicketCache", "true"); loginConfig.put("debug", String.valueOf(true)); authSupplier.setLoginConfig(new Configuration() { @Override public AppConfigurationEntry[] getAppConfigurationEntry(String name) { return new AppConfigurationEntry[] { new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, loginConfig)}; } }); http.setAuthSupplier(authSupplier); HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy(); httpClientPolicy.setAllowChunking(false); httpClientPolicy.setAutoRedirect(true); http.setClient(httpClientPolicy); Holder vLists = new Holder<>(); Holder getListCollectionResult = new Holder<>(); soap.getListCollectionAsync(getListCollectionResult, vLists, res -> { try { GetListCollectionResponse listCollectionResponse = res.get(); ArrayOfSList arrayOfSList = listCollectionResponse.getVLists(); LOG.info("Successfully got {} lists from {}", arrayOfSList.getSList().size(), endpointAddressFinal); for (SList slist : arrayOfSList.getSList()) { LOG.info("Successfully got list {}", slist.getTitle()); } System.exit(0); } catch (Exception e) { LOG.error("List collection response", e); } }); } } 

这是关于JDK7和glassfish的另一个例子。 请注意Nikolay Smirnov的评论。 我使用jdk 7和glassfish 3.1.2。 在此环境中,如果服务器处理自签名证书,则建议的解决方案非常有效。

 // import com.sun.xml.ws.developer.JAXWSProperties; import java.security.GeneralSecurityException; import java.security.SecureRandom; import java.util.Map; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.xml.ws.BindingProvider; import org.apache.cxf.configuration.jsse.TLSClientParameters; import org.apache.cxf.endpoint.Client; import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.transport.http.HTTPConduit; /** * * Usage examples (BindingProvider port): * NaiveSSLHelper.makeWebServiceClientTrustEveryone(port); // GlassFish * NaiveSSLHelper.makeCxfWebServiceClientTrustEveryone(port); // TomEE * * Based on Erik Wramner's example frome here: * http://erikwramner.wordpress.com/2013/03/27/trust-self-signed-ssl-certificates-and-skip-host-name-verification-with-jax-ws/ * * I have extended the functionality when Apache CXF is used. */ public class NaiveSSLHelper { private static final String JAXWS_HOSTNAME_VERIFIER = "com.sun.xml.ws.transport.https.client.hostname.verifier"; // JAXWSProperties.HOSTNAME_VERIFIER; private static final String JAXWS_SSL_SOCKET_FACTORY = "com.sun.xml.ws.transport.https.client.SSLSocketFactory"; // JAXWSProperties.SSL_SOCKET_FACTORY; // In Glassfish (Metro) environment you can use this function (Erik Wramner's solution) public static void makeWebServiceClientTrustEveryone(Object webServicePort) { if (webServicePort instanceof BindingProvider) { BindingProvider bp = (BindingProvider) webServicePort; Map requestContext = bp.getRequestContext(); requestContext.put(JAXWS_SSL_SOCKET_FACTORY, getTrustingSSLSocketFactory()); requestContext.put(JAXWS_HOSTNAME_VERIFIER, new NaiveHostnameVerifier()); } else { throw new IllegalArgumentException( "Web service port " + webServicePort.getClass().getName() + " does not implement " + BindingProvider.class.getName()); } } // In TomEE (Apache CXF) environment you can use this function (my solution) public static void makeCxfWebServiceClientTrustEveryone(Object port) { TrustManager[] trustManagers = new TrustManager[]{ new NaiveTrustManager() }; Client c = ClientProxy.getClient(port); HTTPConduit httpConduit = (HTTPConduit) c.getConduit(); TLSClientParameters tlsParams = new TLSClientParameters(); tlsParams.setSecureSocketProtocol("SSL"); tlsParams.setKeyManagers(new KeyManager[0]); tlsParams.setTrustManagers(trustManagers); tlsParams.setDisableCNCheck(true); httpConduit.setTlsClientParameters(tlsParams); } public static SSLSocketFactory getTrustingSSLSocketFactory() { return SSLSocketFactoryHolder.INSTANCE; } private static SSLSocketFactory createSSLSocketFactory() { TrustManager[] trustManagers = new TrustManager[]{ new NaiveTrustManager() }; SSLContext sslContext; try { sslContext = SSLContext.getInstance("SSL"); sslContext.init(new KeyManager[0], trustManagers, new SecureRandom()); return sslContext.getSocketFactory(); } catch (GeneralSecurityException e) { return null; } } private static interface SSLSocketFactoryHolder { public static final SSLSocketFactory INSTANCE = createSSLSocketFactory(); } private static class NaiveHostnameVerifier implements HostnameVerifier { @Override public boolean verify(String hostName, SSLSession session) { return true; } } private static class NaiveTrustManager implements X509TrustManager { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[0]; } } }