2017-05-29 112 views
0

我嘗試連接到部署在Windows Server上的應用程序。 我使用NTLM。我使用的是Ubuntu和Java8。NTLM身份驗證適用於curl,但不適用於Java

我得到HTTP 401的代碼,但只有當我嘗試從我的Java應用程序連接 。完全相同的 認證細節捲曲請求工作正常,我越來越HTTP 200

curl -v -L --ntlm -u 'myuser\mydomain:mypass' 'http://myip/api/element/151 

這是我的Java代碼 (我簡化了一點,包括唯一的問題相關的東西):

import javax.ws.rs.client.Client; 
import javax.ws.rs.client.ClientBuilder; 
import javax.ws.rs.client.Entity; 
import javax.ws.rs.client.Invocation; 
import javax.ws.rs.client.WebTarget; 
... 
import org.apache.http.auth.NTCredentials; 
import org.apache.http.client.CredentialsProvider; 
import org.apache.http.impl.client.BasicCredentialsProvider; 
import org.glassfish.jersey.apache.connector.ApacheClientProperties; 
import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; 
... 
import org.glassfish.jersey.client.ClientConfig; 
import org.glassfish.jersey.client.ClientProperties; 
import org.glassfish.jersey.client.RequestEntityProcessing; 
... 

class MyConnector { 

    private final Client client; 
    ... 

    protected ClientConfig prepareClientConfig() { 
     ClientConfig config = new ClientConfig(); 
     config.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); 
     config.property(ClientProperties.FOLLOW_REDIRECTS, true); 
     config.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED); 

     CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); 
     credentialsProvider.setCredentials(AuthScope.ANY, new NTCredentials("myuser", "mypassword", 
       "mydomain", "mydomain")); 

     config.property(ApacheClientProperties.CREDENTIALS_PROVIDER, credentialsProvider); 
     config.connectorProvider(new ApacheConnectorProvider()); 

     return config; 
    } 

    ... 

    MyConnector(...) { 

    ... 
    client = ClientBuilder.newClient(prepareClientConfig()); 

    } 


    protected String getDocString(...) throws MyException { 

     WebTarget target = client.target("http://myipi/api").path("element/151"); 

     Invocation.Builder temp = target.request(); 
     Response response = target.request().get(); 

     if (response.getStatus() == Status.OK.getStatusCode()) { 
      String docString = response.readEntity(String.class); 

      return docString; 
     } 

     throw new MyException("Couldn't obtain doc. HTTP error code: " + response.getStatus()); 
    } 

    ... 
} 

需要5-15(!)分鐘來調用getDocString函數。 我也相信應用程序吃了非常大量的RAM,但是沒有其他函數同時運行(程序沒有並行化)。 然後我得到HTTP 401的代碼。

我有一些情況下,當我的Java應用程序工作。這個故事是:

  1. 我的應用程序的工作沒有NTLM
  2. 我的同事加入NTLM到他們的應用程序,我調整了代碼,我的應用程序有401,我捲曲的請求得到了401
  3. 我從Ubuntu 14 LTS升級爲Ubuntu 16.0.2 LTS,我的應用程序有200,捲曲得到200
  4. 我給出了我成立了一個新的服務器上安裝工作的服務器(我沒有任何更多)
  5. ,再次210,我的應用程序有401,捲曲得到200
  6. 我升級到Ubuntu 17.04(非LTS),我的應用程序有200一次,但我不能 重現它,現在一模一樣的請求獲得了401,捲曲得到200

我知道這個問題的: How to send NTLM authenticated post request using jersey? 我使用的代碼,它讓我的應用程序與服務器升級(點3.)結合工作。 但我不知道如何使它再次工作。

我用mitmproxy調試要求,輸出像這樣 (我模糊了Authorization/WWW-Authenticate字段):

Proxy server listening at http://0.0.0.0:8080 
127.0.0.1:39622: clientconnect 
127.0.0.1:39622: request 
    -> Request(GET /api/element/151) 
127.0.0.1:39622: serverconnect 
    -> myip:80 
127.0.0.1:39622: response 
    -> Response(401 Unauthorized, text/html, 1.26k) 
127.0.0.1:39622: GET http://myip/api/element/151 
    User-Agent: Jersey/2.26-b03 (Apache HttpClient 4.5.3) 
    Host: myip 
    Connection: Keep-Alive 
    Accept-Encoding: gzip,deflate 
<< 401 Unauthorized 1.26k 
    Content-Type: text/html 
    Server: Microsoft-IIS/8.5 
    WWW-Authenticate: Negotiate 
    WWW-Authenticate: NTLM 
    X-Powered-By: ASP.NET 
    Date: Mon, 29 May 2017 13:38:36 GMT 
    Content-Length: 1293 
127.0.0.1:39622: request 
    -> Request(GET /api/element/151) 
127.0.0.1:39622: response 
    -> Response(401 Unauthorized, text/html; charset=us-ascii, 341b) 
127.0.0.1:39622: GET http://myip/api/element/151 
    User-Agent: Jersey/2.26-b03 (Apache HttpClient 4.5.3) 
    Host: myip 
    Connection: Keep-Alive 
    Accept-Encoding: gzip,deflate 
    Authorization: NTLM TlRAAA== 
<< 401 Unauthorized 341b 
    Content-Type: text/html; charset=us-ascii 
    Server: Microsoft-HTTPAPI/2.0 
    WWW-Authenticate: NTLM TlRAAABBBBBBAAA== 
    Date: Mon, 29 May 2017 13:38:36 GMT 
    Content-Length: 341 
127.0.0.1:39622: request 
    -> Request(GET /api/element/151) 
127.0.0.1:39622: server communication error: TcpDisconnect('[Errno 104] Connection reset by peer',) 
127.0.0.1:39622: serverdisconnect 
    -> myip:80 
127.0.0.1:39622: serverconnect 
    -> myip:80 
127.0.0.1:39622: response 
    -> Response(401 Unauthorized, text/html, 1.26k) 
127.0.0.1:39622: GET http://myip/api/element/151 
    User-Agent: Jersey/2.26-b03 (Apache HttpClient 4.5.3) 
    Host: myip 
    Connection: Keep-Alive 
    Accept-Encoding: gzip,deflate 
    Authorization: NTLM TlRAAABBBDDDAAA== 
<< 401 Unauthorized 1.26k 
    Content-Type: text/html 
    Server: Microsoft-IIS/8.5 
    WWW-Authenticate: Negotiate 
    WWW-Authenticate: NTLM 
    X-Powered-By: ASP.NET 
    Date: Mon, 29 May 2017 13:44:35 GMT 
    Content-Length: 1293 
127.0.0.1:39622: serverdisconnect 
    -> myip:80 
127.0.0.1:39622: clientdisconnect 

我將有這方面的言論非常感謝。

更新:我也試過Debian8和Debian9。結果是一樣的。我得到401廣告Debian8,更新到Debian9,得到200一次,然後連續401(爲完全相同的請求)。

回答

0

我通過使用JCIFS庫而不是從HttpClient的默認NTLM身份驗證解決了此問題。您可以在Apache頁面上看到示例: https://hc.apache.org/httpcomponents-client-4.5.x/ntlm.html

問題是我找不到一種方法使它與澤西島兼容。澤西島使用javax.ws.rs.client.Client,我不知道如何更新它的AuthScheme(沒有方法來設置它)。所以我切換到org.apache.http.impl.client.CloseableHttpClient並重寫了整個應用程序以使用原始HttpClient方法。

相關問題