[ 
https://issues.apache.org/jira/browse/HTTPCLIENT-2170?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17400633#comment-17400633
 ] 

Erick  commented on HTTPCLIENT-2170:
------------------------------------

[~olegk]

I have simplified the repro code to one file using http-client 5.0.4.

We are still working on getting a public NTLM endpoint, 

meanwhile if you have an NTLM service you can just replace the requestUris with 
one single endpoint and repeat the request several times. 
{code:java}
public class JavaHttpClientWrapper {
  public final CloseableHttpClient httpClient;
  
  public static void main(String[] args) {
    String username = "user";
    String password = "password";

    final String[] requestUris = new String[] {
        
"https://localhost/server/rest/services/CERT_Secured_Basemap/MapServer/tile/0/0/0";,
        
"https://localhost/server/rest/services/CERT_Secured_Basemap/MapServer/tile/63/0/0";,
        
"https://localhost/server/rest/services/CERT_Secured_Basemap/MapServer/tile/16/26166/11433";,
        
"https://localhost/server/rest/services/CERT_Secured_Basemap/MapServer/tile/15/13083/5716";,
        
"https://localhost/server/rest/services/CERT_Secured_Basemap/MapServer/tile/1/0/0";,
        
"https://localhost/server/rest/services/CERT_Secured_Basemap/MapServer/tile/16/26166/11432";,
        
"https://localhost/server/rest/services/CERT_Secured_Basemap/MapServer/tile/14/6541/2858";,
        
"https://localhost/server/rest/services/CERT_Secured_Basemap/MapServer/tile/15/13082/5716";
    };

    try {
      JavaHttpClientWrapper httpClientWrapper = new JavaHttpClientWrapper();
      for(String uri : requestUris) {
        new Thread(() -> {
          httpClientWrapper.makeRequest(uri, username, password);
        }).start();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

  }

  public JavaHttpClientWrapper() throws Exception {

    X509TrustManager trustManager = new X509TrustManager() {
      @Override public void checkClientTrusted(X509Certificate[] 
x509Certificates, String s)
      throws CertificateException {}
      @Override public void checkServerTrusted(X509Certificate[] 
x509Certificates, String s)
      throws CertificateException {}
      @Override public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
      }
    };
    TrustManager[] trustManagers = new TrustManager[] { trustManager };
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, trustManagers, null);

    SSLConnectionSocketFactory sslConnectionSocketFactory = 
SSLConnectionSocketFactoryBuilder.create()
        .setSslContext(sslContext)
        .setTlsVersions(TLS.V_1_2)
        .setHostnameVerifier(new DefaultHostnameVerifier())
        .build();

    Registry sslSocketConnectionRegistry = RegistryBuilder.create()
        .register("http", PlainConnectionSocketFactory.INSTANCE)
        .register("https", sslConnectionSocketFactory).build();

    PoolingHttpClientConnectionManager connectionManager = new 
PoolingHttpClientConnectionManager(sslSocketConnectionRegistry);
    connectionManager.setValidateAfterInactivity(TimeValue.of(1L, 
TimeUnit.SECONDS));
    connectionManager.setMaxTotal(50);
    connectionManager.setDefaultMaxPerRoute(50);

    CacheConfig cacheConfig = CacheConfig.custom()
        .setSharedCache(false).
        setMaxObjectSize(153600L).
        setMaxCacheEntries(600)
        .build();

    this.httpClient = CachingHttpClients.custom()
        .setCacheConfig(cacheConfig)
        .disableAutomaticRetries()
        .setConnectionManager(connectionManager)
        .setDefaultRequestConfig(NetworkDefaults.getDefaultRequestConfig())
        .setUserAgent("test user agent")
        .build();
  }


  public int makeRequest(String url, String username, String password) {
    int httpStatusCode = -1;
    HttpGet httpget = new HttpGet(url);
    try {
      System.out.println(" >>>>>> " + url);
      CloseableHttpResponse response;
        response = httpClient.execute(httpget,
            createContext(url, username, password.toCharArray()));
      httpStatusCode = response.getCode();
      System.out.println("<------" + httpStatusCode + ":" + response);
    } catch (Exception exception) {
      System.out.println("IWA : network request failed: ");
    }

    return httpStatusCode;
  }


  public HttpClientContext createContext(String surl, String username, char[] 
password) throws Exception{
    URL url = new URL(surl);
    String host = url.getHost();
    int port = url.getPort();
    AuthScope authScope = new AuthScope(host, port);
    int finalPort = port >= 0 ? port : 443;
    AuthScope ntlmAuthScope = new AuthScope(null, host, finalPort, null, 
"NTLM");
    HttpClientContext httpClientContext = HttpClientContext.create();

    UsernamePasswordCredentials upc = new UsernamePasswordCredentials(username, 
password);
    NTCredentials ntc = new NTCredentials(this.processUsername(username), 
password, host, null);
    BasicCredentialsProvider provider = new BasicCredentialsProvider();

    provider.setCredentials(authScope, upc);
    provider.setCredentials(ntlmAuthScope, ntc);
    httpClientContext.setCredentialsProvider(provider);
    return httpClientContext;
  }

  public String processUsername(String username) {
    String[] split = username.split("\\\\", 2);
    if (split.length == 2) {
      return split[1] + "@" + split[0];
    }
    return username;
  }
}



{code}
 

> NTLM Authentication not working when sending multiple request concurrently
> --------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-2170
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-2170
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpClient (classic)
>    Affects Versions: 5.0.4, 5.1
>         Environment: Java 1.8 and Android 
>            Reporter: Erick 
>            Priority: Minor
>              Labels: 5.04, 5.1, NTLM, http-client
>         Attachments: NTLMTestSample.zip
>
>
> We migrated our apache version from 4.5.x to 5.0.4 and we have encountered an 
> authentication error using NTLM. 
> We are making multiple requests in different threads to a NTLM secured server 
> concurrently such as: 
> {code:java}
> private fun test_Standalone() {    val username = "username"    val password 
> = "password"    val serverName = "localhost"
>     val requestUrls = arrayOf(        
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/0/0/0";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/63/0/0";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/16/26166/11433";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/15/13083/5716";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/1/0/0";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/16/26166/11432";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/14/6541/2858";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/15/13082/5716";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/15/13083/5715";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/16/26166/11431";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/15/13082/5715";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/14/6541/2857";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/16/26165/11434";,
>         
> "https://${serverName}/server/rest/services/CERT_Secured_Basemap/MapServer/tile/15/13082/5717";
>     )
>     for(url in requestUrls) {        makeRequestAsync(url, username, 
> password)    }}
> {code}
> Some of the data request succeed but others fail with a *401 Unauthorized.*
> **the output looks something like this:
>  
> {code:java}
> <------[Thread-7] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-1] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-4] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-6] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-3] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-10] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-2] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-9] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-13] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-12] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-0] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-11] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-5] 401 :401 Unauthorized HTTP/1.1
> <------[Thread-8] 200 :200 OK HTTP/1.1
> {code}
>  
> Looking at the logs, it seems that the NTLM handshake fails for some request 
> **We found that by synchronizing the method 
> [ProtocolExec.execute()|https://github.com/apache/httpcomponents-client/blob/5.0.x/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ProtocolExec.java#L103],
>  all the NTLM authentication requests succeed and we are able to fetch the 
> data successfully. 
>  
> Attached is the repro java project that we are using. 
> The project only needs an NTLM server and credentials to run. 
>  
> We tested version 5.1 and it was also reproducible. 
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to