http://www.baeldung.com/httpclient-4-basic-authentication
I usually post about HTTP stuff on Twitter - you can follow me there:
1. Overview
This tutorial will illustrate how to configure Basic Authentication on the Apache HttpClient 4.
If you want to dig deeper and learn other cool things you can do with the HttpClient – head on over to the main HttpClient tutorial.
2. Basic Authentication with the API
Let’s start with the standard way of configuring Basic Authentication on the HttpClient – via a CredentialsProvider:
1
2
3
4
5
6
7
8
|
CredentialsProvider provider =
new
BasicCredentialsProvider();
UsernamePasswordCredentials credentials =
new
UsernamePasswordCredentials(
"user1"
,
"user1Pass"
);
provider.setCredentials(AuthScope.ANY, credentials);
HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build();
HttpResponse response = client.execute(
new
HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION));
int
statusCode = response.getStatusLine().getStatusCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
|
As you can see, creating the client with a credentials provider to set it up with Basic Authentication is not difficult.
Now, to understand what HttpClient will actually do behind the scenes, we’ll need to look at the logs:
1
2
3
4
5
6
7
8
9
10
11
|
# ... request is sent with no credentials
[main] DEBUG ... - Authentication required
[main] DEBUG ... - localhost:8080 requested authentication
[main] DEBUG ... - Authentication schemes
in
the order of preference:
[negotiate, Kerberos, NTLM, Digest, Basic]
[main] DEBUG ... - Challenge
for
negotiate authentication scheme not available
[main] DEBUG ... - Challenge
for
Kerberos authentication scheme not available
[main] DEBUG ... - Challenge
for
NTLM authentication scheme not available
[main] DEBUG ... - Challenge
for
Digest authentication scheme not available
[main] DEBUG ... - Selected authentication options: [BASIC]
# ... the request is sent again - with credentials
|
The entire Client-Server communication is now clear:
3. Preemptive Basic Authentication
Out of the box, the HttpClient doesn’t do preemptive authentication – this has to be an explicit decision made by the client.
First, we need to create the HttpContext – pre-populating it with an authentication cachewith the right type of authentication scheme pre-selected. This will mean that the negatiation from the previous example is no longer necessary – Basic Authentication is already chosen:
1
2
3
4
5
6
7
8
9
10
11
12
|
HttpHost targetHost =
new
HttpHost(
"localhost"
,
8080
,
"http"
);
CredentialsProvider credsProvider =
new
BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new
UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS));
AuthCache authCache =
new
BasicAuthCache();
authCache.put(targetHost,
new
BasicScheme());
// Add AuthCache to the execution context
final
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);
|
Now we can use the client with the new context and send the pre-authentication request:
1
2
3
4
5
|
HttpClient client = HttpClientBuilder.create().build();
response = client.execute(
new
HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION), context);
int
statusCode = response.getStatusLine().getStatusCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
|
Let’s look at the logs:
1
2
3
4
5
6
7
|
[main] DEBUG ... - Re-using cached
'basic'
auth scheme
for
http:
//localhost
:8080
[main] DEBUG ... - Executing request GET
/spring-security-rest-basic-auth/api/foos/1
HTTP
/1
.1
[main] DEBUG ... >> GET
/spring-security-rest-basic-auth/api/foos/1
HTTP
/1
.1
[main] DEBUG ... >> Host: localhost:8080
[main] DEBUG ... >> Authorization: Basic dXNlcjE6dXNlcjFQYXNz
[main] DEBUG ... << HTTP
/1
.1 200 OK
[main] DEBUG ... - Authentication succeeded
|
Everything looks OK:
4. Basic Auth with Raw HTTP Headers
Preemptive Basic Authentication basically means pre-sending the Authorization header.
So – instead of going through the rather complex previous example to set it up, we can take control of this header and construct it by hand:
1
2
3
4
5
6
7
8
9
10
11
|
HttpGet request =
new
HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION);
String auth = DEFAULT_USER +
":"
+ DEFAULT_PASS;
byte
[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName(
"ISO-8859-1"
)));
String authHeader =
"Basic "
+
new
String(encodedAuth);
request.setHeader(HttpHeaders.AUTHORIZATION, authHeader);
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(request);
int
statusCode = response.getStatusLine().getStatusCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
|
Let’s make sure this is working correctly:
1
2
3
4
5
6
7
8
|
[main] DEBUG ... - Auth cache not
set
in
the context
[main] DEBUG ... - Opening connection {}->http:
//localhost
:8080
[main] DEBUG ... - Connecting to localhost
/127
.0.0.1:8080
[main] DEBUG ... - Executing request GET
/spring-security-rest-basic-auth/api/foos/1
HTTP
/1
.1
[main] DEBUG ... - Proxy auth state: UNCHALLENGED
[main] DEBUG ... - http-outgoing-0 >> GET
/spring-security-rest-basic-auth/api/foos/1
HTTP
/1
.1
[main] DEBUG ... - http-outgoing-0 >> Authorization: Basic dXNlcjE6dXNlcjFQYXNz
[main] DEBUG ... - http-outgoing-0 << HTTP
/1
.1 200 OK
|
So, even though there is not auth cache, Basic Authentication is still performed correctly and the 200 OK is sent back.
5. Conclusion
This article illustrated various ways to set up and use basic authentication with the Apache HttpClient 4.
The implementation of all these examples and code snippets can be found in the working sample project.
This is an Eclipse based project, so it should be easy to import and run as it is.