Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apache HTTP client 4.3 credentials per request

I have been having a look to a digest authentication example at:

http://hc.apache.org/httpcomponents-client-4.3.x/examples.html

In my scenario the there are several threads issuing HTTP requests and each of them has to be authenticated with their own set of credentials. Additionally, please consider this question is probably very specific for the Apache HTTP client 4.3 onwards, 4.2 handles authentication probably in a different way, although I didn't check it myself. That said, there goes the actual question.

I want to use just one client instance (static member of the class, that is threadsafe) and give it a connection manager to support several concurrent requests. The point is that each request will provide different credentials and I am not seeing the way to assign credentials per request as the credentials provider is set when building the http client. From the link above:

[...]

    HttpHost targetHost = new HttpHost("localhost", 80, "http");
    CredentialsProvider credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(
            new AuthScope(targetHost.getHostName(), targetHost.getPort()),
            new UsernamePasswordCredentials("username", "password"));
    CloseableHttpClient httpclient = HttpClients.custom()
            .setDefaultCredentialsProvider(credsProvider).build();

[...]

Checking:

http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html#d5e600

The code sample in point 4.4 (seek 4.4. HTTP authentication and execution context), seems to say that the HttpClientContext is given the auth cache and the credentials provider and then is passed to the HTTP request. Next to it the request is executed and it seems that the client will get credentials filtering by the host in the HTTP request. In other words: if the context (or the cache) has valid credentials for the target host of the current HTTP request, he will use them. The problem for me is that different threads will perform different requests to the same host.

Is there any way to provide custom credentials per HTTP request?

Thanks in advance for your time! :)

like image 360
Francisco Carriedo Scher Avatar asked Oct 08 '13 16:10

Francisco Carriedo Scher


People also ask

How do I set HttpClient credentials?

You can set the required credentials to the CredentialsProvider object using the setCredentials() method. AuthScope object − Authentication scope specifying the details like hostname, port number, and authentication scheme name. Credentials object − Specifying the credentials (username, password).

Is Apache HttpClient thread safe?

HttpClient is fully thread-safe when used with a thread-safe connection manager such as MultiThreadedHttpConnectionManager.

What is HttpClient authentication?

HTTPS Client Authentication is a more secure method of authentication than either basic or form-based authentication. It uses HTTP over SSL (HTTPS), in which the server authenticates the client using the client's Public Key Certificate (PKC).

What is CloseableHttpClient in Java?

CloseableHttpClient is the base class of the httpclient library, the one all implementations use. Other subclasses are for the most part deprecated. The HttpClient is an interface for this class and other classes. You should then use the CloseableHttpClient in your code, and create it using the HttpClientBuilder .


1 Answers

The problem for me is that different threads will perform different requests to the same host.

Why should this be a problem? As long as you use a different HttpContext instance per thread, execution contexts of those threads are going to be completely indepenent

CloseableHttpClient httpclient = HttpClients.createDefault();
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("user:pass"));
HttpClientContext localContext = HttpClientContext.create();
localContext.setCredentialsProvider(credentialsProvider);

HttpGet httpget = new HttpGet("http://localhost/");

CloseableHttpResponse response = httpclient.execute(httpget, localContext);
try {
    EntityUtils.consume(response.getEntity());
} finally {
    response.close();
}
like image 90
ok2c Avatar answered Sep 25 '22 14:09

ok2c