Call SOAP web-service using Windows proxy settings in Java - java

I'm writing a standalone java app.
I have to use default system (Windows XP, 7) proxy settings to call the SOAP web-services using HTTPS protocol.
To determine system proxy settings I use the ProxySelector class. Here's the code:
System.setProperty("java.net.useSystemProxies", "true");
List proxies = ProxySelector.getDefault().select(new URI("https://www.google.com/"));
for (Iterator iter = proxies.iterator(); iter.hasNext();) {
Proxy proxy = (Proxy) iter.next();
InetSocketAddress address = (InetSocketAddress) proxy.address();
if (address == null) {
UTLogger.getLogger().debug("No proxy (direct connection)");
} else {
if (proxy.type().equals(Proxy.Type.HTTP)) {
System.setProperty("http.proxyHost", address.getHostName());
System.setProperty("http.proxyPort", String.valueOf(address.getPort()));
System.setProperty("https.proxyHost", address.getHostName());
System.setProperty("https.proxyPort", String.valueOf(address.getPort()));
} else if (proxy.type().equals(Proxy.Type.SOCKS)) {
System.setProperty("socksProxyHost", address.getHostName());
System.setProperty("socksProxyPort", String.valueOf(address.getPort()));
}
}
}
System.setProperty("java.net.useSystemProxies", "false");
And here's how I initialize connection:
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new TrustDummy()}, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
servicePort = new MyPort(new URL(wsdlLocation), new QName(nameSpaceURI, localPart)).getMyPortSoap();
I don't understand why there is no Proxy.Type.HTTPS? If i call a web-service method i get the following errors.
With http proxy set:
javax.xml.ws.WebServiceException: Failed to access the WSDL at: ht tps://...?wsdl. It failed with: Got Unrecognized SSL message, plaintext connection? while opening stream from ht tps://...?wsdl.
and with https proxy set:
javax.xml.ws.WebServiceException: Failed to access the WSDL at: ht tps://...?wsdl. It failed with: Got Unable to tunnel through proxy. Proxy returns "HTTP/1.0 403 Forbidden" while opening stream from ht tps://...?wsdl.
Am I doing it wrong?

Related

Proxy authorization - always connects even when credentials are wrong

The connection to a proxy trough my code always able to connect even when wrong/no credentials are given. When I connect to the same server trough curl 407 error is given when it supposed to.
What am I doing wrong?
Code -
if (proxyProperties != null && proxyProperties.isUseProxy()) {
final String proxyHost = proxyProperties.getHost();
final Integer proxyPort = proxyProperties.getPort();
final HttpHost proxyHttpHost = new HttpHost(proxyHost, proxyPort);
clientBuilder.setProxy(proxyHttpHost);
asyncClientBuilder.setProxy(proxyHttpHost);
logger.info("Proxy connection configured, proxy host: {}", proxyHttpHost);
if (proxyProperties.isUseProxyAuthentication() && !StringUtils.isEmpty(proxyProperties.getUser())) {
final CredentialsProvider credentialsProvider = getProxyAuthenticator(proxyProperties, logger);
clientBuilder.setDefaultCredentialsProvider(credentialsProvider);
asyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
}

How can I set https.proxyHost and https.proxyPort for individual HttpsURLConnections?

I'm trying to make HTTPS requests through a proxy. Here's what I've got so far, based on code from this question:
try {
HttpsURLConnection connection = (HttpsURLConnection) new URL("https://proxylist.geonode.com/api/proxy-list?limit=1&page=1&sort_by=speed&sort_type=asc&protocols=https").openConnection();
connection.setRequestMethod("GET");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("user-agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36");
connection.setConnectTimeout(30000);
connection.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String rawJSON = reader.readLine();
if(rawJSON == null) throw new IOException("No data");
JSONObject data = new JSONObject(rawJSON).getJSONArray("data").getJSONObject(0);
String ipAddress = data.getString("ip"), port = data.getString("port");
System.setProperty("https.proxyHost", ipAddress);
System.setProperty("https.proxyPort", port);
SSLContext sslContext = SSLContext.getInstance("SSL");
// set up a TrustManager that trusts everything
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() { return null; }
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
} }, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier((arg0, arg1) -> true);
HttpsURLConnection testConnection = (HttpsURLConnection) new URL("https://example.com").openConnection();
testConnection.connect();
StringBuilder result = new StringBuilder();
String line;
try(BufferedReader reader2 = new BufferedReader(new InputStreamReader(testConnection.getInputStream()))) {
while ((line = reader2.readLine()) != null) result.append(line);
}
System.out.println(result);
} catch(Exception e) {
e.printStackTrace();
}
The code works, but there's a problem. My application (https://encyclosearch.org) is multithreaded, and I need to make some requests through a proxy, and some directly. Since system properties are global, if I set https.proxyHost and https.proxyPort using System.setProperty, some requests that aren't supposed to go through the proxy will go through the proxy.
I can use java.net.Proxy like this:
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ipAddress, Integer.parseInt(port)));
HttpsURLConnection testConnection = (HttpsURLConnection) new URL("http://example.com").openConnection(proxy);
But that only works for HTTP proxies, not HTTPS ones, so I can't make HTTPS requests. There's no Proxy.Type.HTTPS.
Any help would be greatly appreciated. Thanks in advance.
If you choose which connections go through a proxy and which do not by the destination url then you can use the property http.nonProxyHosts. This property is used for http and https as the documentation states:
for the "non proxy hosts" list, the HTTPS protocol handler will use the same as the http handler (i.e. http.nonProxyHosts).
You set the property value by adding patterns of urls separated by | For example:
System.setProperty("http.nonProxyHosts", ”localhost|host.example.com”)
You could also use ProxySelector class for choosing which connections go through a proxy. for more info (a bit old):
https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
As for the absence of Proxy.Type.HTTPS, it is because a proxy in general is not the final destination so the secure connection will be with the final destination not the proxy itself. There is such thing as SSL tunneling through a proxy, but i am not well informed about it.
With #Bashi's help, I figured it out. For direct connections, I used:
url.openConnection(Proxy.NO_PROXY);
This works for Jsoup, too:
Document document = Jsoup.connect("https://example.com").proxy(Proxy.NO_PROXY).get();
Explanation from https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html:
Now, this guarantees you that this specific URL will be retrieved though a direct connection bypassing any other proxy settings, which can be convenient.

Proxy returns "HTTP/1.1 407 Proxy Authorization Required" in production but works in local

Getting error while calling a api in production but works in local.
Used same proxy as in local 10.235.88.30 and port 8080
calling through jersey client:-
com.sun.jersey.api.client.Client client = new Client(
new URLConnectionClientHandler(new HttpURLConnectionFactory() {
#Override
public HttpURLConnection getHttpURLConnection(final URL url) throws IOException {
Proxy proxy;
proxy = new Proxy(Proxy.Type.HTTP,
new InetSocketAddress("10.235.88.30", 8080));
return (HttpURLConnection) url.openConnection(proxy);
}
}), new DefaultClientConfig());
Should return response but getting proxy error.
com.sun.jersey.api.client.ClientHandlerException: java.io.IOException: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authorization Required"

HttpsURLConnection.setDefaultHostnameVerifier: method verify not invoked

I configure HttpsUrlConnection like this:
HttpsURLConnection.setDefaultSSLSocketFactory(sslFactory);
HttpsURLConnection.setDefaultHostnameVerifier(new DummyHostnameVerifier());
DummyHostnameVerifier:
public class DummyHostnameVerifier implements HostnameVerifier {
#Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
}
Of course, it's only part of configuration. But the problem is that verify method in DummyHostnameVerifier isn't invoked.
When I test my application on local machine, glassfish 3 server, verify invoked and I'm not recieving any exceptions.
But when I test it on remote environment, verify isn't invoked, and I recieve this:
java.io.IOException: The https URL hostname does not match the Common Name (CN) on the server certificate. To disable this check (NOT recommended for production) set the CXF client TLS configuration property "disableCNCheck" to true.
On remote env app runs on jboss 5.
Maybe this depends on some jboss config? I can't understand, where default hostname verifier changed after setting my verifier.
I think if you want to by pass the certificateValidation you would need to create Trustmanager which will not go for certificate validation
HttpsURLConnection.setDefaultHostnameVerifier(new DummyHostnameVerifier());
// Create a TrustManager which wont validate certificate chains start
javax.net.ssl.TrustManager[] trustAllCertificates = new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new miTM();
trustAllCertificates[0] = tm;
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
sc.init(null, trustAllCertificates, null);
// Create a TrustManager which wont validate certificate chains end
HttpsURLConnection.setDefaultSSLSocketFactory(sslFactory);
Could you please try with above code and let me know if you get the resolution ?
The problem was in following: somehow there wasn't action name in message to server.
I configured connection like this:
HttpsURLConnection.setDefaultSSLSocketFactory(sslFactory);
HttpsURLConnection.setDefaultHostnameVerifier(new DummyHostnameVerifier());
URL url = null;
try {
url = new URL(endpoint + "/wsdl");
} catch (MalformedURLException e) {
LOG.error(e.getMessage());
}
javax.xml.ws.Service s = MyService.create(url, new QName(MyService.NAMESPACE, MyService.SERVICE));
ServiceSoap port = s.getPort(ServiceSoap.class);
Map<String, Object> reqCtx = ((BindingProvider)port).getRequestContext();
reqCtx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
reqCtx.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
reqCtx.put(BindingProvider.SOAPACTION_URI_PROPERTY, actionName);
Client client = ClientProxy.getClient(port);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnection(ConnectionType.CLOSE);
http.setClient(httpClientPolicy);
TLSClientParameters tls = new TLSClientParameters();
tls.setSSLSocketFactory(sslFactory);
tls.setDisableCNCheck(true);
http.setTlsClientParameters(tls);
So, port configured and everything began to work.

Apache Http Client 4.0.1 SSL Proxy

I am using Apache Http client 4.0.1 for communicating with the server. I already have a secure/non secure client code that works just fine.
Recently the new addition being to add proxy to this code, so i added the following piece of code to do that (currently non secure proxy),
HttpHost proxy = new HttpHost("localhost", 5555);
httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
This has worked fine with a non secure request. However i am having trouble with a secure (https) request with the same code.
Get the below exception (it tries a few time before failing),
Mar 12, 2014 11:14:27 AM org.apache.http.impl.client.DefaultRequestDirector tryConnect
INFO: I/O exception (org.apache.http.NoHttpResponseException) caught when connecting to the target host: The target server failed to respond
Mar 12, 2014 11:14:27 AM org.apache.http.impl.client.DefaultRequestDirector tryConnect
INFO: Retrying connect
org.apache.http.NoHttpResponseException: The target server failed to respond
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:95)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:62)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:254)
at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:289)
at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:252)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.receiveResponseHeader(ManagedClientConnectionImpl.java:191)
at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:300)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:127)
at org.apache.http.impl.client.DefaultRequestDirector.createTunnelToTarget(DefaultRequestDirector.java:899)
at org.apache.http.impl.client.DefaultRequestDirector.establishRoute(DefaultRequestDirector.java:818)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:644)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
at com.poc.test.SSLTest.main(SSLTest.java:88)
Tried following things,
For https requests, i added both "http" as well as "https" to the schema registry, using the same SSLFactory as the one used for "https".
Changed the proxy to,
HttpHost proxy = new HttpHost("localhost", 5555, "https");
However in both cases it failed with,
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:572)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:640)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
at com.poc.test.SSLTest.main(SSLTest.java:89)
Note - I am running a non secure proxy on my localhost via tcpmon.
EDIT: Here is the code i am using for the SSL with proxy communication,
DefaultHttpClient httpClient = new DefaultHttpClient();
try {
SSLContext ctx = SSLContext.getInstance("TLSv1.1");
TrustManager[] trustManagers = getTrustManagers("jks", new FileInputStream(new File("C:\\SSLKeyStore.ks")), "changeit");
ctx.init(null, trustManagers, new SecureRandom());
HttpGet httpget = new HttpGet("https://localhost:8844/Channels/HTTP/getData");
System.out.println("executing request" + httpget.getRequestLine());
SSLSocketFactory factory = new SSLSocketFactory(ctx);
factory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager manager = httpClient.getConnectionManager();
manager.getSchemeRegistry().register(new Scheme("https", 443, factory));
manager.getSchemeRegistry().register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
HttpHost proxy = new HttpHost("localhost", 5555, "http");
httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
HttpResponse response = httpClient.execute(httpget);
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
}
EntityUtils.consume(entity);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
httpClient.getConnectionManager().shutdown();
}
Any ideas of what is happening, what am i missing with respect to https and proxy.
Latest EDIT - Even tried their example code (ClientExecuteProxy.java) as is, that too failed with proxy. Is this functionality broken?
HttpHost proxy = new HttpHost("127.0.0.1", 8080, "http");
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
HttpHost target = new HttpHost("issues.apache.org", 443, "https");
HttpGet req = new HttpGet("/");
System.out.println("executing request to " + target + " via " + proxy);
HttpResponse rsp = httpclient.execute(target, req);
HttpEntity entity = rsp.getEntity();
System.out.println("----------------------------------------");
System.out.println(rsp.getStatusLine());
Header[] headers = rsp.getAllHeaders();
for (int i = 0; i<headers.length; i++) {
System.out.println(headers[i]);
}
System.out.println("----------------------------------------");
if (entity != null) {
System.out.println(EntityUtils.toString(entity));
}
} finally {
// When HttpClient instance is no longer needed,
// shut down the connection manager to ensure
// immediate deallocation of all system resources
httpclient.getConnectionManager().shutdown();
}
}
Thanks,
Vicky
Off the top of my head I'd say that you are dealing with a certificate trust issue.
Without seeing how you are setting up the connection specifically I can say with no certainty though.
The "peer not authenticated" means that somewhere along the line the verification of the certificates as presented by one or more of the servers cannot be verified.
EDIT
Since the proxy is under your control you have a load of flexibility at this time.
Please see this SO article, it may suit your needs.

Categories