2017-05-29 10 views
0

Windows Serverにデプロイされているアプリケーションに接続しようとしています。 私はNTLMを使用します。私はUbuntuとJava8を使用しています。NTLM認証はcurlで動作しますが、Javaでは動作しません

私はHTTP 401コードを取得していますが、私がJavaアプリケーションから に接続しようとすると発生します。まったく同じ 認証の詳細とカールの要求は、私がHTTP 200を取得しています、[OK]を動作します:

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()); 
    } 

    ... 
} 

getDocString関数を呼び出すには5分(!)分かかります。 他の機能は同時に実行されていませんが(プログラムは並列化されていませんが)、アプリケーションは異常に大量のRAM、 を食べているとも思います。 次に、私はHTTP 401コードを取得します。

私のJavaアプリケーションがうまく動作したことがありました。話はした:

  1. 私のアプリケーションは、NTLM
  2. せずに私の同僚を働いていた自分のアプリにNTLMを追加し、私はコードを調整し、私のアプリは401を持って、私のカール要求が401
  3. を得た私は、Ubuntu 16.0.2 LTSUbuntu 14 LTSからアップグレード私のアプリは200、カールは、私はで再び、私は新しいサーバーをセットアップし、セットアップが働いているサーバー(私はより多くのそれを持っていない)
  4. を与えた200
  5. を得ました210、私のアプリは401、カールは、私がUbuntu 17.04にアップグレード
  6. 200を得ました(非LTS)、私のアプリは一度200を得たが、私は 、カールが取得する今、まったく同じ要求が401が取得する、それを再現することはできません200

私はこの質問を知っている:私は、コードを使用し、それは私のアプリは、(ポイント3.で)サーバーのアップグレードとの組み合わせで動作するように許可され How to send NTLM authenticated post request using jersey? 。 しかし、私はそれを再び働かせる方法を知らない。

私がリクエストをデバッグするために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広告を入手しました。Debian9に更新されたDebian8は、200を一度取得してから、続けて401(まったく同じリクエスト)です。

答えて

0

この問題は、HttpClientのデフォルトのNTLM認証の代わりにJCIFSライブラリを使用して解決しました。この例は、Apacheページで確認できます。 https://hc.apache.org/httpcomponents-client-4.5.x/ntlm.html

問題は、Jerseyと互換性のある方法を見つけることができなかったことです。 Jerseyはjavax.ws.rs.client.Clientを使用しており、AuthSchemeの更新方法はわかりませんでした(設定する方法はありません)。そこで私はorg.apache.http.impl.client.CloseableHttpClientに切り替え、生のHttpClientメソッドを使用するためにアプリケーション全体を書き直しました。

関連する問題