为 CXF httpConduit 设置 ProxyAuthorizationPolicy 不起作用
set ProxyAuthorizationPolicy for CXF httpConduit doesn't work
我正在使用 CXF 3.1.5,我正在尝试使其与 proxy 一起使用。如果代理没有用户名和密码,那么它就可以工作;如果代理有用户名和密码,则它不起作用。这是我的代码:
//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 实现了HTTPConduitFactory,并且会在TLSAndProxySupportedHTTPConduit 中创建一个扩展URLConnectionHTTPConduit 的TLSAndProxySupportedHTTPConduit,这里是相关的代理设置代码:
//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());
}
请记住,如果代理没有用户名和密码,一切正常 fine.and 如果加载 WSDL 定义的目标 URL 以 https 开头(我需要 https),代理不起作用。如果它以http开头,那么使用用户名和密码的代理就可以正常工作。
找到解决方案:
原因是
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.
参考:http://www.javaworld.com/article/2077475/core-java/java-tip-111--implement-https-tunneling-with-jsse.html
和 https://community.oracle.com/thread/1534538
然后你可以覆盖 URLConnectionHTTPConduit 的方法 setupConnection。
@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);
}
在 decorateHttpsURLConnection 方法中:
httpsConnection.setSSLSocketFactory(new SSLTunnelSocketFactory(getProxy(), sslContext.getSocketFactory()));
我正在使用 CXF 3.1.5,我正在尝试使其与 proxy 一起使用。如果代理没有用户名和密码,那么它就可以工作;如果代理有用户名和密码,则它不起作用。这是我的代码:
//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 实现了HTTPConduitFactory,并且会在TLSAndProxySupportedHTTPConduit 中创建一个扩展URLConnectionHTTPConduit 的TLSAndProxySupportedHTTPConduit,这里是相关的代理设置代码:
//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());
}
请记住,如果代理没有用户名和密码,一切正常 fine.and 如果加载 WSDL 定义的目标 URL 以 https 开头(我需要 https),代理不起作用。如果它以http开头,那么使用用户名和密码的代理就可以正常工作。
找到解决方案:
原因是
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.
参考:http://www.javaworld.com/article/2077475/core-java/java-tip-111--implement-https-tunneling-with-jsse.html
和 https://community.oracle.com/thread/1534538
然后你可以覆盖 URLConnectionHTTPConduit 的方法 setupConnection。
@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);
}
在 decorateHttpsURLConnection 方法中:
httpsConnection.setSSLSocketFactory(new SSLTunnelSocketFactory(getProxy(), sslContext.getSocketFactory()));