HTTPs over a proxy with apache http client - java

I have a http client which is based on the apache http client and it seems to have no problem with ssl certificates. I have a unit test for both globally recognized certs and self signed certs with a custom SSLSocketFactory.
However when I ran the same code behind a proxy, it stopped working. I keep getting this dreaded exception:
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:352)
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)
I reduced the code to the bare minimum and it still throws the same exception. The code:
URI uri = new URI("https://www.google.com");
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
new HttpHost("proxy.int", 8080, "https"));
HttpUriRequest request = new HttpGet(uri);
HttpResponse response = client.execute(request);
I wasn't sure if it uses the default ssl settings if nothing is specified so I added it explicitly as well:
URI uri = new URI("https://www.google.com");
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
new HttpHost("proxy.int", 8080, "https"));
client.getConnectionManager().getSchemeRegistry().register(
new Scheme("https", 443, SSLSocketFactory.getSystemSocketFactory()));
HttpUriRequest request = new HttpGet(uri);
HttpResponse response = client.execute(request);
I also tried the getSocketFactory() (not entirely sure what the difference is with getSystemSocketFactory()), still the same error though.
EDIT:
The proxy has optional authentication and I have tried both with and without. The authentication information was set using the following code:
client.getCredentialsProvider().setCredentials(
new AuthScope("proxy.int", 8080),
new UsernamePasswordCredentials("user", "password")
);
Exactly the same error.

The problem was in the proxy declaration, I had to specify "http" instead of "https":
client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
new HttpHost("proxy.int", 8080, "http"));

Related

How can I contact an ssl secured webservice without a cert in a java app?

I have a very basic java webservice call...
public static String contactWebservice(){
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpHost target = new HttpHost(“www.someurl.com”, 443, "https");
HttpGet getRequest = new HttpGet("PARAMETERS FOR WEBSERVICE");
HttpResponse httpResponse = httpclient.execute(target, getRequest);
…more code...
I need to turn this into a SSL call without a cert. Much like a browser contacts an ssl secured webpage and gets data back without having a cert. I've tried many different methods but nothing has worked so far. I keep getting "peer not authenticated" errors.

SharePoint 2010 REST Java authentication

I was happy to access SharePoint using PowerShell. It just picked -DefaultCredential and I didn't have to worry about that. That was for prototyping.
But my actual code is Java. Now I am not sure about this at all.
Even though I make REST calls, even SOAP would fail if I don't authenticate properly.
Method 1 : NTLM
Here the only thing I am not sure about is the workstation ID. I login using Citrix to a VM and there is an explicit Workstation ID. I use that.
Returns 401.
DefaultHttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://teams.host.com/_vti_bin/listdata.svc/");
NTCredentials credentials = new NTCredentials("user", 'pass', "workstation", "Domain");
client.getCredentialsProvider().setCredentials(new AuthScope("teams.host.com",80), credentials);
HttpResponse response = client.execute(request);
Method 2 : Basic authentication.
HttpGet request = new HttpGet("http://teams.host.com/_vti_bin/listdata.svc/");
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("user", "password"));
CloseableHttpClient httpClient =
HttpClientBuilder.create().setDefaultCredentialsProvider(credentialsProvider).build();
HttpResponse response = httpClient.execute(request);
Returns 401.
What other method do I use ? Digest ? Since I don't know how -DefaultCredential in PowerShell worked I am back to the drawing board.
How should I investigate this ? I must be making some basic mistakes in this Java code. The flow is not right. That is my supposition.
So from Apache HttpClient this is the code that connects to SharePoint 2010. The workstation ID is the one used when I use Citrix XenDesktop to login to a Windows machine. I am able to get the result of my REST Get request.
This uses NTLM authentication.
DefaultHttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://teams.host.com/_vti_bin/listdata.svc/");
NTCredentials credentials = new NTCredentials("user", 'pass', "workstation", "Domain");
client.getCredentialsProvider().setCredentials(new AuthScope("teams.host.com",80), credentials);
HttpResponse response = client.execute(request);

HttpClient : hostname didn't match - accessible from browser but not from code

I am trying to access a website from my code using HttpClient :
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("https://www.datamed.org/search.php?query=gene&searchtype=data");
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = httpclient.execute(httpget, responseHandler);
This is the error i am getting :
Exception in thread "main" javax.net.ssl.SSLException: hostname in certificate didn't match: <www.datamed.org> != <ucrexdc.ucsd.edu> OR <ucrexdc.ucsd.edu>
I checked the certificate from browser, it seems correct, with correct names.
Not sure from where it is picking up ucrexdc.ucsd.edu .
The code does work if I use a proxy.
Gone through a lot of similar issues on StackOverflow, but in most cases the server was under user's control. In my case, this is an already existing website. and i have this problem only for this website.
Can it be a problem with my environment?
UPDATE:
I found out that both the websites (datamed.org and ucrexdc.ucsd.edu) have the same IP , 169.228.51.21 . Can it be a problem, why doesn't the browser have issues with this?
UPDATE 2:
I was using apache http-client 4.3.1,
When i updated to 4.4.1, it was resolved. the issue was most possibly related to SNI.
HttpClient provides two implementations for Hostname verification.
DefaultHostnameVerifier
NoopHostnameVerifier
by default HttpClient uses DefaultHostnameVerifier implementation. You can try the different hostname verifier implementation.
SSLContext sslContext = SSLContexts.createSystemDefault();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
HttpClient httpClient = HttpClientBuilder.create().setSSLSocketFactory(sslsf).build();

How to authenticate with httpclient 4.3

I've just upgraded to org.apache.httpcomponents.httpclient 4.3. Previously I created a client and did pre-emptive authentication like this:
final HttpClient client = new DefaultHttpClient();
final HttpRequestBase request = new HttpGet(url);
request.addHeader(BasicScheme.authenticate( new UsernamePasswordCredentials(username,password), "UTF-8", false));
Now that this is deprecated I have to create a client and authenticate like this:
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
clientBuilder = clientBuilder.setDefaultCredentialsProvider(credentialsProvider);
However instead of authenticating and making a successful GET I get a 302 in response. I think this could be fixed by setting pre-emptive authentication, but I can't find how. Maybe I have authentication in this second example all wrong?
Can I get some pointers, please?
It's not clear whether this is actually a real problem.
HTTP 302 is a redirection. You need to follow the redirect.

Authentication fails in HttpClient but OK in browser

I'm using HttpClient 4.0 to get some XML from the remote host. When I use URL such as https://user:pwd#www.somesite.com it works fine in the browser but fails in the HttpClient with this stacktrace (follows). Any suggestions? I'm using SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER while setting ThreadSafeClientConnManager to handle HTTPS requests
The code (partial):
final HttpGet get= new HttpGet(url);
final HttpResponse response = this.client.execute(get);
return new BasicResponseHandler().handleResponse(response);
Stacktrace:
01-05 22:34:03.783: ERROR/SearchResults(11565):
Failed to process request to URL:
https://user:pwd#www.somesite.com/products/foo/meta/xml_proper_encoding.jsp?version=1
01-05 22:34:03.783: ERROR/SearchResults(11565):
org.apache.http.client.HttpResponseException: Unauthorized
Pass UsernamePasswordCredentials like in this example, not in the URL.

Categories

Resources