I am trying to develop a java http client with apache httpcomponents 4.0.1. This client calls the page "https://myHost/myPage". This page is protected on the server by a JNDIRealm with a login form authentication, so when I try to get https://myHost/myPage I get a login page. I tried to bypass it unsuccessfully with the following code :
//I set my proxy
HttpHost proxy = new HttpHost("myProxyHost", myProxyPort);
//I add supported schemes
SchemeRegistry supportedSchemes = new SchemeRegistry();
supportedSchemes.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
supportedSchemes.register(new Scheme("https", SSLSocketFactory
.getSocketFactory(), 443));
// prepare parameters
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, "UTF-8");
HttpProtocolParams.setUseExpectContinue(params, true);
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params,
supportedSchemes);
DefaultHttpClient httpclient = new DefaultHttpClient(ccm, params);
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
proxy);
//I add my authentication information
httpclient.getCredentialsProvider().setCredentials(
new AuthScope("myHost/myPage", 443),
new UsernamePasswordCredentials("username", "password"));
HttpHost host = new HttpHost("myHost", 443, "https");
HttpGet req = new HttpGet("/myPage");
//show the page
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String rsp = httpClient.execute(host, req, responseHandler);
System.out.println(rsp);
When I run this code, I always get the login page, not myPage. How can I apply my credential parameters to avoid this login form?
Any help would be fantastic
HttpClient doesn't support form login. What you are trying to do is Basic Auth, which does't work with form login.
You can simply trace the form post for login page and send the POST request from HttpClient.
Related
Using SOAP UI, I am able to successfully invoke the REST GET call with basic authentication
GET https://app.test.com/testing/rest/authentication-point/authentication HTTP/1.1
Accept-Encoding: gzip,deflate
Authorization: Basic aPOjYVclOmIzABFhZjVpJES=
Host: app.test.com
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
I received response code as 200.
Similar request, When I tried to invoke via java client, it is giving 400 status code.
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("User", "Password"));
final HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = null;
response = client.execute(
new HttpGet("https://app.test.com/testing/rest/authentication-point/authentication"),
context);
int statusCode = response.getStatusLine().getStatusCode();
This code worked properly when the host was HTTP. Recently a VIP is added and made as HTTPS, after which it is not working. Please suggest a fix for this.
You need to use ssl with http client:
TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
SSLSocketFactory sf = new SSLSocketFactory(
acceptingTrustStrategy, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https", 8443, sf));
ClientConnectionManager ccm = new PoolingClientConnectionManager(registry);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("User", "Password"));
final HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
DefaultHttpClient httpClient = new DefaultHttpClient(ccm);
HttpGet getMethod = new HttpGet(new HttpGet("https://app.test.com/testing/rest/authentication-point/authentication"),context);
HttpResponse response = httpClient.execute(getMethod);
int statusCode = response.getStatusLine().getStatusCode();
After trying out so many options, below code worked for me.
HttpHost targetHost = new HttpHost("app.test.com", 443, "https");
AuthCache authCache = new BasicAuthCache();
authCache.put(targetHost, new BasicScheme());
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("User", "Password"));
final HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = null;
response = client.execute(
new HttpGet("https://app.test.com/testing/rest/authentication-point/authentication"),
context);
After defining a HTTP host with scheme as https, and setting them to context using AuthCache, the call went through successfully.
I can get to https://pushover.net/ using chrome browser, but when i try to get to the same website using java to connect to the api and send data it fails.
this is my code
HttpClient httpClient = (HttpClient) HttpClientBuilder.create()/*.setProxy(proxy)*/.build();
HttpPost post = new HttpPost("https://api.pushover.net/1/messages.json");
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("token", apiToken));
nvps.add(new BasicNameValuePair("user", userKey));
nvps.add(new BasicNameValuePair("message", message));
post.setEntity(new UrlEncodedFormEntity(nvps, Charset.defaultCharset()));
//point A
HttpResponse deviceResponse = httpClient.execute(post);
//point B
it gets to point A, but then takes ages to get to point B and it gives an exception when it does.
The Exception is
org.apache.http.conn.HttpHostConnectException: Connect to api.pushover.net:443 (api.pushover.net/108.59.13.232] failed: Connection timer out: connect.
I have tried using a proxy with the below code above the rest
HttpHost proxy = new HttpHost("url",9090,"https");
httpClient = (HttpClient) HttpClientBuilder.create().setProxy(proxy).build();
This gives me a
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
I then also tried adding
Authenticator.setDefault(
new Authenticator() {
#Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
authUser, authPassword.toCharArray());
}
}
);
System.setProperty("http.proxyUser", authUser);
System.setProperty("http.proxyPassword", authPassword);
but it gives the same SSLHandshakeException.
I have seen things on creating keystores, but that will only work on my machine, I want something that will work in code and allow me to deploy this app to 1000's of machines, without having to do extra manual config to each.
Is there anything Better i should be doing?
I have fixed it with this code in place of the httpClient at the beginning.
HttpHost proxy = new HttpHost(PROXY_URL, 8080);
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
AuthCache authCache = new BasicAuthCache();
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(PROXY_URL, 8080, AuthScope.ANY_HOST, "ntlm"), new NTCredentials(authUser, authPassword, "",PROXY_DOMAIN));
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);
httpClient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).setRoutePlanner(routePlanner).build();
I am trying to post a SharePoint list item to a SharePoint 2010 list using Java client.
I am able to read the SP list items using below code but I am not sure how to write to the SharePoint.
For the post operation, I am getting http 401 error.
Any guidance will be greatly appreciated.
GET Operation:
String url = "https://organization.company.com/sites/Ateam/_vti_bin/ListData.svc/TableLoadInfo"; DefaultHttpClient client = new DefaultHttpClient();
NTCredentials credentials = new NTCredentials(username, password, hostname, domain);
AuthScope scope = new AuthScope(hostname, 443);
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(null, new TrustManager[] { trustmanager }, null);
SSLSocketFactory sf = new SSLSocketFactory(sslcontext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Scheme https = new Scheme("https", 443, sf);
client.getConnectionManager().getSchemeRegistry().register(https);
client.getCredentialsProvider().setCredentials(scope, credentials);
HttpGet request = new HttpGet(url);
//request.addHeader("Accept", "application/xml");
request.addHeader("Accept", "application/json;odata=verbose");
HttpResponse response = client.execute(request);
POST Operation:
String url = "https://organization.company.com/sites/Ateam/_vti_bin/ListData.svc/TableLoadInfo";
DefaultHttpClient client = new DefaultHttpClient();
NTCredentials credentials = new NTCredentials(username, password, hostname, domain);
AuthScope scope = new AuthScope(hostname, 443);
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(null, new TrustManager[] { trustmanager }, null);
SSLSocketFactory sf = new SSLSocketFactory(sslcontext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Scheme https = new Scheme("https", 443, sf);
client.getConnectionManager().getSchemeRegistry().register(https);
client.getCredentialsProvider().setCredentials(scope, credentials);
// POST a data
HttpPost request = new HttpPost(url);
request.addHeader("Accept", "application/json;odata=verbose");
request.addHeader("Content-type", "application/json;odata=verbose");
// request.addHeader("X-RequestDigest", FormDigestValue);
request.addHeader("X-HTTP-Method", "POST");
request.addHeader("If-Match", "*");
JSONStringer json = (JSONStringer) new JSONStringer().object().key("Table_Name").value("TableName 1")
.key("Load_Frequency").value("Weekly").key("Cycle").value("CURRENT").endObject();
StringEntity se = new StringEntity(json.toString());
request.setEntity(se);
HttpResponse response = client.execute(request);
When you post data to SharePoint you have to add "FormDigestValue" inside the header.
Please Note you have commented the line "request.addHeader("X-RequestDigest", FormDigestValue);".
That is the reason you get 401 Error.
First you have to get the "FormDigestValue" value form your current site.
Then add that value inside the header.
Following Code shows the way to get the FormDigestValue.
String digestqueryURL = serverurl + subsite + "/" + "_api/contextinfo";
HttpPost httpPost = new HttpPost(digestquery);
httpPost.addHeader("Accept", "application/json;odata=verbose");
httpPost.addHeader("X-ClientService-ClientTag", "SDK-JAVA");
HttpResponse response = httpClient.execute(httpPost);
byte[] content = EntityUtils.toByteArray(response.getEntity());
String jsonString = new String(content, "UTF-8");
JSONObject json = new JSONObject(jsonString);
String FormDigestValue = json.getJSONObject("d")
.getJSONObject("GetContextWebInformation")
.getString("FormDigestValue");
Then add the FormDigestValue to the header when you do the post operations.
request.addHeader("X-RequestDigest", FormDigestValue);
I'm trying to access a RESTful web service through the Android Emulator on my PC, which uses a proxy to connect to the internet.
I have code working fine to access the web service on an actual Android device that has its own data connection with the following code:
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
HttpGet request = new HttpGet("http://mytesturl.com/services/serviceName");
UsernamePasswordCredentials creds =
new UsernamePasswordCredentials("username", "password");
request.addHeader(BasicScheme.authenticate(creds, "UTF-8", false));
HttpResponse response = client.execute(request);
I've tried a number of approaches to try to get the Emulator to allow connection through the proxy, but none have worked.
Note, I do have the INTERNET enabled in AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
Attempt 1 - Setting Properties:
This produces an UnknownHostException for the URL of my service at the execute() call
Properties props = System.getProperties();
props.put("http.proxyHost", "httpproxy.mycompany.com");
props.put("http.proxyPort", "80");
Attempt 2 - Setting the proxy in the DefaultHttpClient:
This produces an UnknownHostException for the actual proxy
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
HttpHost proxy = new HttpHost("httpproxy.mycompany.com", 80);
client.getCredentialsProvider().setCredentials(
new AuthScope("httpproxy.mycompany.com", 80),
new UsernamePasswordCredentials("username", "password"));
client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
HttpGet request = new HttpGet("http://mytesturl.com/services/serviceName");
UsernamePasswordCredentials cred =
new UsernamePasswordCredentials("username", "password");
request.addHeader(BasicScheme.authenticate(cred, "UTF-8", false));
HttpResponse response = client.execute(request);
Attempt 3 - Setting the proxy in the HttpGet
This produces an UnknownHostException for the URL in my HttpGet
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
HttpGet request = new HttpGet("http://mytesturl.com/services/serviceName");
UsernamePasswordCredentials cred =
new UsernamePasswordCredentials("username", "password");
request.addHeader(BasicScheme.authenticate(cred, "UTF-8", false));
Header bs = new BasicScheme().authenticate(
new UsernamePasswordCredentials("username", "password"),
request);
request.addHeader("Proxy-Authorization", bs.getValue());
HttpResponse response = client.execute(request);
I'm not sure what else to try. I'm open to any suggestions.
Having the same problem, I succeeded with a variation on attempt 3 (code below), the cruicial difference being the setProperty statements. Note that the web service I am calling does not require authentication so I'm only setting the proxy authorization header.
System.setProperty("java.net.useSystemProxies", "false");
System.setProperty("http.proxyHost", "123.56.7.9");
System.setProperty("http.proxyPort", "8080");
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
HttpGet request = new HttpGet("web service url");
Header bs = new BasicScheme().authenticate(
new UsernamePasswordCredentials("NETWORKID", "netpassword"),
request);
request.addHeader("Proxy-Authorization", bs.getValue());
HttpResponse response = client.execute(request);
did you use -http-proxy http://: emulator command line option or "Settings" -> "Wireless & Networks" -> "Mobile Networks" -> "Access Point Names" -> "Telkila" or Home > Menu > Settings > Wireless Controls > Mobile Networks > Access Point Names?
I've been trying to implement connection pooling for my application using Apache HTTPClient (v4.1). The problem is that the client always makes only two connections when run, though there are enough threads running parallel. I have been trying to modify the code for a while now, but nothing has helped yet.
I'm using ThreadSafeClientConnManager for connection pooling and set the MaxTotal and DefaulMaxPerRoute to values I want.
Is there anything that comes to your mind first that I might want to check?
Here's that code segment that I use to create the client.
DefaultHttpClient createClient() {
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, new Integer(60000));
params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, new Integer(60000));
params.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https", sf, 6443));
registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, registry);
cm.setMaxTotal(2 * maxConnections);
cm.setDefaultMaxPerRoute(maxConnections);
HttpHost localhost = new HttpHost("localhost");
cm.setMaxForRoute(new HttpRoute(localhost), maxConnections);
HttpHost sdpTargetHost = new HttpHost("webserviceIP", webservicePort, "https");
cm.setMaxForRoute(new HttpRoute(sdpTargetHost, null, true), maxConnections);
return new DefaultHttpClient(cm, params);
}
The client returned by this function is used in Runnables managed by a ThreadPoolExecutor. The Runnables use the client, and has these lines:
HttpResponse response = httpClient.execute(httpPost, context);
HttpEntity entity = response.getEntity();
....
EntityUtils.consume(entity);
From what I know, the EntityUtils.consume(entity) will notify the connection manager that the connection is no longer used, and thus will release the connection to be used by other threads. So I'm guessing the connection management is alright.
I guess I've provided enough info, please tell me if I'm to add anything more.
Thanks
OK. I've found the solution, thanks to oleg for pointing out the logging, and to google and all the forums. All I had to do was define the class with only the connection manager, and then set HttpParams using HttpClient.setParams(). So the code will look something like this:
DefaultHttpClient createClient() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https", sf, 6443));
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(registry);
cm.setMaxTotal(maxConnections);
cm.setDefaultMaxPerRoute(maxConnections);
HttpHost targetHost = new HttpHost("webserviceIP", webservicePort, "https");
cm.setMaxForRoute(new HttpRoute(targetHost, null, true), maxConnections);
return new DefaultHttpClient(cm);
}
And right before using the client,
DefaultHttpClient httpClient = createClient();
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, new Integer(60000));
params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, new Integer(60000));
params.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true);
httpClient.setParams(params);
There apparently is no difference in the code logically, but this fixed my problem. I presume this probably is some sorta bug in the HttpClient 4.1 API.
I was not able to set this option in cm
cm.setDefaultMaxPerRoute(maxConnections);
It was necessary to do so:
ConnPerRoute perRoute = new ConnPerRouteBean(100);
ConnManagerParams.setMaxConnectionsPerRoute(params, perRoute);
ConnManagerParams.setMaxTotalConnections(params, 100);
ConnManagerParams.setTimeout(params, 15000);