Jason Jason - 1 month ago 11
Java Question

set ProxyAuthorizationPolicy for CXF httpConduit doesn't work

I'm Using CXF 3.1.5, I'm trying to make it work with proxy. if there is no username and password for the proxy, then it works; if there is an username and password for the proxy, then it doesn't work. here is my code:


//to create my own http conduit
bus.setExtension(new TLSAndProxySupportedHTTPConduitFactory(settings, HTTPConduitFactory.class);
//to get wsdl definition
Definition definition = bus.getExtension(WSDLManager.class).getDefinition(uri);


TLSAndProxySupportedHTTPConduitFactory implements HTTPConduitFactory, and will create a TLSAndProxySupportedHTTPConduit which extends URLConnectionHTTPConduit, in TLSAndProxySupportedHTTPConduit, here is the related code for proxy settings:


//HTTPClientPolicy settings works
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setProxyServer(proxy.getHostName());
httpClientPolicy.setProxyServerPort(proxy.getPort());

this.setClient(httpClientPolicy);

if (proxy.getUserName() != null) {
//ProxyAuthorizationPolicy settings doesn't work
this.getProxyAuthorization().setUserName(proxy.getUserName());
this.getProxyAuthorization().setPassword(proxy.getPassword());

}


Please do remember if the proxy has no username and password, everything works just fine.and if the target URL for loading WSDL definition is started with https(https is required for me), the proxy doesn't work. if it's started with http, then the proxy with username and password works well.

Answer

Find a solution:
The Reason is

The Java Secure Socket Extension (JSSE) library from Sun Microsystems lets you access a secure Web server from behind a firewall via proxy tunneling. To do this, the JSSE application needs to set the https.ProxyHost and https.ProxyPort system properties. The tunneling code in JSSE checks for "HTTP 1.0" in the proxy's response. If your proxy, like many, returns "HTTP 1.1", you will get an IOException. In this case, you need to implement your own HTTPS tunneling protocol.

Referance:http://www.javaworld.com/article/2077475/core-java/java-tip-111--implement-https-tunneling-with-jsse.html
and https://community.oracle.com/thread/1534538


Then you could overwrite method setupConnection of URLConnectionHTTPConduit.

@Override
protected void setupConnection(Message message, Address address, HTTPClientPolicy csPolicy) throws IOException {
    super.setupConnection(message, address, csPolicy);
    HttpURLConnection connection = (HttpURLConnection) message.get(KEY_HTTP_CONNECTION);
    decorateHttpsURLConnection((HttpsURLConnection) connection);\
    message.put(KEY_HTTP_CONNECTION, connection);
}

in the method decorateHttpsURLConnection:

httpsConnection.setSSLSocketFactory(new SSLTunnelSocketFactory(getProxy(), sslContext.getSocketFactory()));
Comments