Unauthorized connection after Authenticating with HTTPCLIENT - java

So I'm getting Unauthorized error after authorizing with http client. The website im trying to access has NTLM authentication. If someone could help with this issue it would be appreciated.
public class ClientAuthentication {
public static void main(String[] args) throws Exception {
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
httpclient.getCredentialsProvider().setCredentials(
new AuthScope("website", 80),
new UsernamePasswordCredentials("username", "password"));
HttpGet httpget = new HttpGet("http://cdg5.intranet.bell.ca/BlackFoot/Ont/");
System.out.println("executing request" + httpget.getRequestLine());
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);
} finally {
// When HttpClient instance is no longer needed,
// shut down the connection manager to ensure
// immediate deallocation of all system resources
httpclient.getConnectionManager().shutdown();
}
}
}
and here is the result im getting
"executing requestGET http://cdg5.intranet.bell.ca/BlackFoot/Ont/
HTTP/1.1
HTTP/1.1 401 Unauthorized Response content length: 1656"

Related

Apache HttpClient with POST file-uploading won't do a basic auth on mysterious reasons

I am trying to upload a file by the POST method with the Apache HttpClient library.
I used the example code for the preemptive basic authentification here:
package ahcs;
// many imports, press ctrl-o in eclipse
public class App {
static final String url = "http://127.0.0.1:64738/test/";
static final String content = "test\nfile\ndata";
static final String httpUser = "testuser";
static final String httpPasswd = "testPassword";
static final String fileUploadFieldName = "uploadData";
static final String fileName = "upload.dat";
public static void main(String[] args) {
System.err.println("Uploading to URL " + url);
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost(url);
httpPost.setProtocolVersion(HttpVersion.HTTP_1_1);
MultipartEntityBuilder mpEntityBuilder =
MultipartEntityBuilder.create();
mpEntityBuilder.setMode(HttpMultipartMode.RFC6532);
mpEntityBuilder.addBinaryBody(fileUploadFieldName,
content.getBytes(), ContentType.DEFAULT_BINARY, fileName);
httpPost.setEntity(mpEntityBuilder.build());
System.err.println("executing request " + httpPost.getRequestLine());
HttpEntity resEntity = null;
try {
// Really simple HTTP Authentification, grat Apache
HttpHost httpHost = URIUtils.extractHost(new URI(url));
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(httpUser, httpPasswd));
AuthCache authCache = new BasicAuthCache();
authCache.put(httpHost, new BasicScheme());
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);
HttpResponse response = httpclient.execute(httpPost);
resEntity = response.getEntity();
System.err.println(response.getStatusLine().toString());
if (resEntity != null) {
System.err.println(EntityUtils.toString(resEntity));
}
int status = response.getStatusLine().getStatusCode();
if (status != HttpStatus.SC_OK) {
throw new HttpResponseException(status,
"Upload error! (" + status + ")");
}
EntityUtils.consume(resEntity);
httpclient.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Unfortunately, it doesn't do what I want. The request what the apache httpclient gives, is this (I got this by listening from the command line with an nc -p 64738 -l command):
POST /test/ HTTP/1.1
Content-Length: 249
Content-Type: multipart/form-data; boundary=PIrvSJ07MLxTV2rC4d-5ZfoL3CvJFJdJqO4i
Host: 127.0.0.1:64738
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.4 (Java/1.8.0_151)
Accept-Encoding: gzip,deflate
--PIrvSJ07MLxTV2rC4d-5ZfoL3CvJFJdJqO4i
Content-Disposition: form-data; name="uploadData"; filename="upload.dat"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
test
file
data
--PIrvSJ07MLxTV2rC4d-5ZfoL3CvJFJdJqO4i--
As we can see, everything is okay, except that the authentification header is simply missing.
Why is it so? What is the bug?
According to RFC7617 you need only one header "Authorization" with values "Basic " + login:passord in Base64 encoding to successefuly pass Basic authorization.
Your code is correct, except one thing - when you call httpPost.execute you are not pass execution context, and AuthCache and CredentialsProvider wasn't used at all.
package ahcs;
// many imports, press ctrl-o in eclipse
public class App {
static final String url = "http://127.0.0.1:64738/test/";
static final String content = "test\nfile\ndata";
static final String httpUser = "testuser";
static final String httpPasswd = "testPassword";
static final String fileUploadFieldName = "uploadData";
static final String fileName = "upload.dat";
public static void main(String[] args) {
System.err.println("Uploading to URL " + url);
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost(url);
httpPost.setProtocolVersion(HttpVersion.HTTP_1_1);
MultipartEntityBuilder mpEntityBuilder =
MultipartEntityBuilder.create();
mpEntityBuilder.setMode(HttpMultipartMode.RFC6532);
mpEntityBuilder.addBinaryBody(fileUploadFieldName,
content.getBytes(), ContentType.DEFAULT_BINARY, fileName);
httpPost.setEntity(mpEntityBuilder.build());
System.err.println("executing request " + httpPost.getRequestLine());
HttpEntity resEntity = null;
try {
// Really simple HTTP Authentification, grat Apache
HttpHost httpHost = URIUtils.extractHost(new URI(url));
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(httpUser, httpPasswd));
AuthCache authCache = new BasicAuthCache();
authCache.put(httpHost, new BasicScheme());
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);
// context was missed
HttpResponse response = httpclient.execute(httpPost, context);
resEntity = response.getEntity();
System.err.println(response.getStatusLine().toString());
if (resEntity != null) {
System.err.println(EntityUtils.toString(resEntity));
}
int status = response.getStatusLine().getStatusCode();
if (status != HttpStatus.SC_OK) {
throw new HttpResponseException(status,
"Upload error! (" + status + ")");
}
EntityUtils.consume(resEntity);
httpclient.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
But for Basic Auth using this API may be a bit verbose, it was designed to support many different authorization schemes.
If you know what charset server will use to decode Authorization header (suppose it UTF-8), you can write one-liner:
httpPost.setHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString((httpUser + ':' + httpPasswd).getBytes‌​("UTF-8")));

HttpEntity reset after closing and throws java.net.SocketException

public static String sendRequest(UUICRequest requset) throws
ClientProtocolException, IOException
{
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10 * 1000).build();
CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
HttpGet httpGet = new HttpGet(requset.toUrl());
CloseableHttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
response.close();
httpClient.close();
return EntityUtils.toString(entity, "UTF-8");
}
It throws java.net.SocketException: socket closed.
I debugged and ran this program line by line, just found entity changed when excuted:
response.close();
httpClient.close();
So I rewrite my code:
public static String sendRequest(UUICRequest requset) throws
ClientProtocolException, IOException
{
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10 * 1000).build();
CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
HttpGet httpGet = new HttpGet(requset.toUrl());
CloseableHttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
String ret = EntityUtils.toString(entity, "UTF-8");//+
response.close();
httpClient.close();
return ret;//M
}
This code works as expected and successfully ends.
My question is, why httpclient will reset entity after closing response and httpClient?
My question is, why httpclient will reset entity after closing response and httpClient?
Streaming HTTP entities (such as those returned with an HttpResponse) are attached to the underlying connection in order to be able to stream data out without any intermediate buffering. Closing HttpResponse before response content has been fully consumed causes the underlying connection to get reset.

Apache http post example

I am very new to this Apache http client. I have an URL to make a webservice call to one of the service. I was successfully executed with the GET request but I am trying to execute this with the POST request but I am not getting any response. I was unable to get the content from the entity.
My URL: "https://maps.googleapis.com/maps/api/place/details/xml?reference=CoQBcQAAAEZ7yCju-0lhU7sZIBBe_On9jYImWzZ9Zt5rIg1tX6zaH02dHrQMHF1LFHY1_yUuXzsUf6m6-rrQJ8Ec_mGxBYtV85Wyb4anakaUi3QuZj7ygJXB3Fd5x69k_4UnDKMmEBNa410vbCXgQOGIkHCbNpcbC8ENxmVlUrqiifmdfuLgEhCtPATMhFRdsjuyAL_j__OEGhTnqujRRMYy_5-kxzcqCdMY4_1dbA&sensor=true&key=key1";
This was executed with the GET method. Below u can see my code.
public class HttpClientPostExample {
public static void main(String[] args) throws ClientProtocolException,
IOException {
String url = "https://maps.googleapis.com/maps/api/place/details/xml?";
HttpClient client = HttpClientBuilder.create().build();
// HttpRequest httpRequest = HttpsClientImpl.createRequest("Post", url);
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
nameValuePairList
.add(new BasicNameValuePair(
"reference",
"CoQBcQAAAEZ7yCju-0lhU7sZIBBe_On9jYImWzZ9Zt5rIg1tX6zaH02dHrQMHF1LFHY1_yUuXzsUf6m6-rrQJ8Ec_mGxBYtV85Wyb4anakaUi3QuZj7ygJXB3Fd5x69k_4UnDKMmEBNa410vbCXgQOGIkHCbNpcbC8ENxmVlUrqiifmdfuLgEhCtPATMhFRdsjuyAL_j__OEGhTnqujRRMYy_5-kxzcqCdMY4_1dbA"));
nameValuePairList.add(new BasicNameValuePair("sensor", "true"));
nameValuePairList.add(new BasicNameValuePair("key",
"AIzaSyBA0Hu3is9qIJ5v6NEuofigk0y-aQwqiP0"));
httpPost.addHeader("User-Agent", "User-Agent");
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairList, "UTF-8"));
HttpResponse response = client.execute(httpPost);
System.out.println(response.getStatusLine().getStatusCode());
Header[] headerArray = response.getAllHeaders();
for (Header header : headerArray) {
System.out.println("Header Name: " + header.getName()
+ " Header Value: " + header.getValue());
}
}
Can any one help me on this. Is this the right approach to make a POST request...???
How can I get actual URL before firing/calling the execute method...???
Try to change your client instantiation technique from
HttpClient client = HttpClientBuilder.create().build();
to
DefaultHttpClient client = new DefaultHttpClient();
and to make sure that your entity has been fully consumed, make a call to EntityUtils.consume(entity) before showing the reponse headers:
...
HttpResponse response = client.execute(httpPost);
EntityUtils.consume(response.getEntity());
Header[] headerArray = response.getAllHeaders();
for (Header header : headerArray) {
System.out.println("Header Name: " + header.getName()
+ " Header Value: " + header.getValue());
}

HTTP/1.1 400 Bad Request on httpGet with Base Authentication

I made an application that do a httpGet.
My application uses my own certificate and so the server requires a user login.
For certificate i used this tutorial.
For httpGet I've made this implementation:
HttpClient client = new CustClient(getApplicationContext()); // HttpClient that uses my certificates
// Example send http request
final String url = "https://ip:port/";// <--in my implementation i've a right url
HttpResponse response = null;
HttpGet httpGet = new HttpGet(url);
//login
httpGet.addHeader("Authorization", "Basic "+Base64.encodeToString("root:root".getBytes(),Base64.DEFAULT));
StringBuilder testo = null;
try {
response = client.execute(httpGet);
InputStream contenuto = response.getEntity().getContent();
BufferedReader rd = new BufferedReader(new InputStreamReader(contenuto));
String line;
// Read response until the end
while ((line = rd.readLine()) != null) {
testo.append(line);
}
} catch (Exception e) {
}
Whyen i make client.execute(httpGet) response is HTTP/1.1 400 Bad Request. Why?
Is correct to authenticate as in my code?
the problem was the Authorization header.
We have to use:
httpGet.addHeader("Authorization", "Basic "+Base64.encodeToString("root:root".getBytes(),Base64.NO_WRAP));
Instead of:
httpGet.addHeader("Authorization", "Basic "+Base64.encodeToString("root:root".getBytes(),Base64.DEFAULT));
because the DEFAULT parameter add "CR" line terminator at the end of string and it's uncorrect if you'll use it that header.

Handling HttpClient Redirects

I'm POSTing some data to a server that is answering a 302 Moved Temporarily.
I want HttpClient to follow the redirect and automatically GET the new location, as I believe it's the default behaviour of HttpClient. However, I'm getting an exception and not following the redirect :(
Here's the relevant piece of code, any ideas will be appreciated:
HttpParams httpParams = new BasicHttpParams();
HttpClientParams.setRedirecting(httpParams, true);
SchemeRegistry schemeRegistry = registerFactories();
ClientConnectionManager clientConnectionManager = new ThreadSafeClientConnManager(httpParams, schemeRegistry);
HttpClient httpClient = new DefaultHttpClient(clientConnectionManager, httpParams)
HttpPost postRequest = new HttpPost(url);
postRequest.setHeader(HTTP.CONTENT_TYPE, contentType);
postRequest.setHeader(ACCEPT, contentType);
if (requestBodyString != null) {
postRequest.setEntity(new StringEntity(requestBodyString));
}
return httpClient.execute(postRequest, responseHandler);
For HttpClient 4.3:
HttpClient instance = HttpClientBuilder.create()
.setRedirectStrategy(new LaxRedirectStrategy()).build();
For HttpClient 4.2:
DefaultHttpClient client = new DefaultHttpClient();
client.setRedirectStrategy(new LaxRedirectStrategy());
For HttpClient < 4.2:
DefaultHttpClient client = new DefaultHttpClient();
client.setRedirectStrategy(new DefaultRedirectStrategy() {
/** Redirectable methods. */
private String[] REDIRECT_METHODS = new String[] {
HttpGet.METHOD_NAME, HttpPost.METHOD_NAME, HttpHead.METHOD_NAME
};
#Override
protected boolean isRedirectable(String method) {
for (String m : REDIRECT_METHODS) {
if (m.equalsIgnoreCase(method)) {
return true;
}
}
return false;
}
});
The default behaviour of HttpClient is compliant with the requirements of the HTTP specification (RFC 2616)
10.3.3 302 Found
...
If the 302 status code is received in response to a request other
than GET or HEAD, the user agent MUST NOT automatically redirect the
request unless it can be confirmed by the user, since this might
change the conditions under which the request was issued.
You can override the default behaviour of HttpClient by sub-classing DefaultRedirectStrategy and overriding its #isRedirected() method.
It seem http redirect is disable by default. I try to enable, it work but I'm still got error with my problem. But we still can handle redirection pragmatically. I think your problem can solve:
So old code:
AndroidHttpClient httpClient = AndroidHttpClient.newInstance("User-Agent");
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
long contentSize = httpResponse.getEntity().getContentLength();
This code will return contentSize = -1 if http redirect happend
And then I handle redirect by myself after trying enable default follow redirection
AndroidHttpClient client;
HttpGet httpGet;
HttpResponse response;
HttpHeader httpHeader;
private void handleHTTPRedirect(String url) throws IOException {
if (client != null)
client.close();
client = AndroidHttpClient.newInstance("User-Agent");
httpGet = new HttpGet(Network.encodeUrl(url));
response = client.execute(httpGet);
httpHeader = response.getHeaders("Location");
while (httpHeader.length > 0) {
client.close();
client = AndroidHttpClient.newInstance("User-Agent");
httpGet = new HttpGet(Network.encodeUrl(httpHeader[0].getValue()));
response = client.execute(httpGet);
httpHeader = response.getHeaders("Location");
}
}
In use
handleHTTPRedirect(url);
long contentSize = httpResponse.getEntity().getContentLength();
Thanks
Nguyen
My solution is using HttClient. I had to send the response back to the caller. This is my solution
CloseableHttpClient httpClient = HttpClients.custom()
.setRedirectStrategy(new LaxRedirectStrategy())
.build();
//this reads the input stream from POST
ServletInputStream str = request.getInputStream();
HttpPost httpPost = new HttpPost(path);
HttpEntity postParams = new InputStreamEntity(str);
httpPost.setEntity(postParams);
HttpResponse httpResponse = null ;
int responseCode = -1 ;
StringBuffer response = new StringBuffer();
try {
httpResponse = httpClient.execute(httpPost);
responseCode = httpResponse.getStatusLine().getStatusCode();
logger.info("POST Response Status:: {} for file {} ", responseCode, request.getQueryString());
//return httpResponse ;
BufferedReader reader = new BufferedReader(new InputStreamReader(
httpResponse.getEntity().getContent()));
String inputLine;
while ((inputLine = reader.readLine()) != null) {
response.append(inputLine);
}
reader.close();
logger.info(" Final Complete Response {} " + response.toString());
httpClient.close();
} catch (Exception e) {
logger.error("Exception ", e);
} finally {
IOUtils.closeQuietly(httpClient);
}
// Return the response back to caller
return new ResponseEntity<String>(response.toString(), HttpStatus.ACCEPTED);
For HttpClient v5, just use the below:
httpClient = HttpClientBuilder.create()
.setRedirectStrategy(new DefaultRedirectStrategy() {
#Override
public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context)
throws ProtocolException {
return false;
}
}).build();

Categories

Resources