Further debugged the issue and investigated httpclient code.

For Basic Auth , DefaultUserTokenHandler.getAuthPrincipal(..) retrurns null
.

Should i change this implementation and return userName instead?

On Wed, Sep 17, 2014 at 6:05 PM, Sukhdev Singh <[email protected]>
wrote:

> One more observation on it.
>
> I don't see this issue when I lock httpclient.execute (...) and let it run
> by 1 thread at a time.
> Looks like in httpclient 4.1.2, httpclient.execute(...) is not thread safe
> as credentials are being overwritten by another thread.
>
> How to fix this issue. Any setting in httpclient?
>
> Regards
> Sukhdev
>
> On Wed, Sep 17, 2014 at 12:45 AM, Sukhdev Singh <[email protected]>
> wrote:
>
>> I am using httpclient 4.1.3 in my project.
>>
>> I am creating single httpclient instance with ThreadSafeClientConnManager.
>> I don't see alternative to ThreadSafeClientConnManager in httpclient
>> 4.1.3.
>>
>> Intermittently I am experiencing that http request being made for
>> another user which is not the intended user. I am setting credentials in
>> AuthState and using localHttpClient.
>>
>> My test includes -
>>  - Six threads running in parallel each calling REST API 10 time
>>  - Endpoint URL is same for all request so HttpHost is same.
>>  - There are six authenticating users. Each thread correspond to 1 thread.
>>
>> Pasting code below. Please let me know if i am missing anything in main
>> code. I am not printing my test code here.
>>
>> import java.io.IOException;
>>
>> import java.security.cert.CertificateException;
>>
>> import java.security.cert.X509Certificate;
>>
>>
>> import org.apache.http.HttpException;
>>
>> import org.apache.http.HttpHost;
>>
>> import org.apache.http.HttpRequest;
>>
>> import org.apache.http.HttpRequestInterceptor;
>>
>> import org.apache.http.auth.AuthScope;
>>
>> import org.apache.http.auth.AuthState;
>>
>> import org.apache.http.client.CredentialsProvider;
>>
>> import org.apache.http.client.params.HttpClientParams;
>>
>> import org.apache.http.client.protocol.ClientContext;
>>
>> import org.apache.http.conn.ClientConnectionManager;
>>
>> import org.apache.http.conn.scheme.Scheme;
>>
>> import org.apache.http.conn.scheme.SchemeRegistry;
>>
>> import org.apache.http.conn.ssl.SSLSocketFactory;
>>
>> import org.apache.http.conn.ssl.TrustStrategy;
>>
>> import org.apache.http.impl.auth.BasicScheme;
>>
>> import org.apache.http.impl.client.DefaultHttpClient;
>>
>> import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
>>
>> import org.apache.http.params.HttpConnectionParams;
>>
>> import org.apache.http.protocol.ExecutionContext;
>>
>> import org.apache.http.protocol.HttpContext;
>>
>> import org.apache.log4j.Logger;
>>
>>
>> public class BasicAuthRestClient extends AbstractRestClient{
>>
>> private static int HTTP_CONN_TIMEOUT = 30*1000; //30 second
>>
>> private static int HTTP_SOCKET_TIMEOUT = 5*60*1000;  //5 minute
>>
>> private static int HTTP_MAX_CONN = 1000;
>>
>> private static int HTTP_MAX_PER_ROUTE = 100;
>>
>>
>>     public BasicAuthRestClient(String baseUrl){
>>
>>
>>     this.baseUrl = baseUrl;
>>
>>         SchemeRegistry registry = new SchemeRegistry();
>>
>>         SSLSocketFactory socketFactory;
>>
>> try {
>>
>> socketFactory = new SSLSocketFactory(new TrustStrategy() {
>>
>> @Override
>>
>> public boolean isTrusted(X509Certificate[] arg0, String arg1)
>>
>> throws CertificateException {
>>
>> return true;
>>
>> }
>>
>> }, org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
>> );
>>
>>          registry.register(new Scheme("https", HTTP_SSL_PORT,
>> socketFactory));
>>
>> } catch (Exception e) {
>>
>> logger.error("exception in creating SSLSocketFactory", e);
>>
>> }
>>
>>
>>  ClientConnectionManager connMgr = new
>> ThreadSafeClientConnManager(registry);
>>
>>         ((ThreadSafeClientConnManager)connMgr).setMaxTotal(HTTP_MAX_CONN
>> );
>>
>>         ((ThreadSafeClientConnManager)connMgr).setDefaultMaxPerRoute(
>> HTTP_MAX_PER_ROUTE);
>>
>>
>>
>>     httpClient = new DefaultHttpClient(connMgr);
>>
>>     //setting request interceptor
>>
>>     ((DefaultHttpClient)httpClient).addRequestInterceptor(new
>> HttpBasicAuthInterceptor(), 0);
>>
>>
>>         HttpConnectionParams.setConnectionTimeout(httpClient.getParams(),
>> HTTP_CONN_TIMEOUT);
>>
>>         HttpConnectionParams.setSoTimeout(httpClient.getParams(),
>> HTTP_SOCKET_TIMEOUT);
>>
>>         HttpConnectionParams.setStaleCheckingEnabled(httpClient.getParams(),
>> true);
>>
>>         HttpConnectionParams.setTcpNoDelay(httpClient.getParams(), true);
>>
>>
>>         HttpClientParams.setAuthenticating(httpClient.getParams(), true);
>>
>>         HttpClientParams.setRedirecting(httpClient.getParams(), false);
>>
>>     }
>>
>>
>>     static class HttpBasicAuthInterceptor implements
>> HttpRequestInterceptor {
>>
>>         public void process(
>>
>>                 final HttpRequest request,
>>
>>                 final HttpContext context) throws HttpException,
>> IOException {
>>
>>             AuthState authState = (AuthState)
>> context.getAttribute(ClientContext.TARGET_AUTH_STATE);
>>
>>             CredentialsProvider credProvider =
>> (CredentialsProvider)context.getAttribute(
>>
>>             ClientContext.CREDS_PROVIDER);
>>
>>
>>
>>             HttpHost targetHost = (HttpHost)context.getAttribute(
>>
>>             ExecutionContext.HTTP_TARGET_HOST);
>>
>>
>>
>>             authState.setCredentials(credProvider.getCredentials(
>>
>>                        new AuthScope(targetHost.getHostName(),
>> targetHost.getPort())));
>>
>>
>>
>>             authState.setAuthScheme((BasicScheme)context.getAttribute(
>> "preemptive-auth"));
>>
>>         }
>>
>>     }
>>
>>
>>     private HttpContext createHttpContext(String userName, String
>> password){
>>
>> String host = Utils.getHostName(baseUrl);
>>
>>
>> BasicHttpContext localcontext = new BasicHttpContext();
>>
>> BasicScheme basicAuth = new BasicScheme();
>>
>> localcontext.setAttribute("preemptive-auth", basicAuth);
>>
>> CredentialsProvider credProvider = new BasicCredentialsProvider();
>>
>> credProvider.setCredentials(
>>
>>           new AuthScope(host, HTTP_SSL_PORT),
>>
>>           new UsernamePasswordCredentials(userName, password));
>>
>> localcontext.setAttribute(ClientContext.CREDS_PROVIDER, credProvider);
>>
>>  localcontext.setAttribute(
>>
>>           ClientContext.TARGET_AUTH_STATE, new AuthState());
>>
>> HttpHost targetHost = new HttpHost(host, HTTP_SSL_PORT, "https");
>>
>> localcontext.setAttribute(ExecutionContext.HTTP_TARGET_HOST, targetHost);
>>
>> return localcontext;
>>
>>  }
>>
>>
>>
>>     public String doGet(final String url,
>>
>>     final String userName, final String password) throws
>> RestClientException {
>>
>>         HttpGet httpget = new HttpGet(this.baseUrl + url);
>>
>>         HttpResponse response = null;
>>
>> try {
>>
>>     HttpContext localcontext = createHttpContext(userName, password);
>>
>>
>> response = httpClient.execute(httpget, localcontext);
>>
>> return handleHttpResponse(response);
>>
>> } catch (ClientProtocolException e) {
>>
>> throw new RestClientException(e);
>>
>> } catch (IllegalStateException e) {
>>
>> throw new RestClientException(e);
>>
>> } catch (IOException e) {
>>
>> throw new RestClientException(e);
>>
>> } catch (Exception e){
>>
>> throw new RestClientException(e);
>>
>> }finally{
>>
>> try {
>>
>> EntityUtils.consume(response.getEntity());
>>
>> } catch (Exception e) {
>>
>> logger.warn("Exception in EntityUtils.consume - ", e);
>>
>> }
>>
>>  httpClient.getConnectionManager().closeIdleConnections(60000,
>>
>> TimeUnit.MILLISECONDS);
>>
>> httpClient.getConnectionManager().closeExpiredConnections();
>>
>> }
>>
>>     }
>>
>> }
>>
>>
>> Regards
>> Sukhdev
>>
>
>

Reply via email to