12

Web サービスにアクセスする必要がある Java アプリケーション (アプレットではない) があります。Web サービスのプロキシは JAX-WS で生成されており、正常に動作しているようです。あるシナリオでは、NTLM 認証を要求するように設定された Web プロキシ サーバー (実際には Squid 3.0) を介して通信する必要があります。

Sun の JRE 1.6.0_14 で実行すると、HTTP URL にアクセスするためのすべてが正常に機能し、何も変更する必要はありません。組み込みの NTLM オーセンティケーターが作動し、すべてシームレスに機能します。ただし、Web サービス URL が HTTPS URL の場合、Web サービス呼び出しは Sun のコードの奥深くで失敗します。

com.sun.xml.internal.ws.client.ClientTransportException: HTTP transport error: java.lang.NullPointerException
        at com.sun.xml.internal.ws.transport.http.client.HttpClientTransport.getOutput(HttpClientTransport.java:121)
        at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:142)
        at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:83)
        at com.sun.xml.internal.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:105)
        at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:587)
        at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:546)
        at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:531)
        at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:428)
        at com.sun.xml.internal.ws.client.Stub.process(Stub.java:211)
        at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(SEIStub.java:124)
        at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:98)
        at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
        at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107)
        ... our web service call ...
Caused by: java.lang.NullPointerException
        at sun.net.www.protocol.http.NTLMAuthentication.setHeaders(NTLMAuthentication.java:175)
        at sun.net.www.protocol.http.HttpURLConnection.doTunneling(HttpURLConnection.java:1487)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:164)
        at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:896)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
        at com.sun.xml.internal.ws.transport.http.client.HttpClientTransport.getOutput(HttpClientTransport.java:109)
        ... 16 more

Sun のバグ データベースを調べると、そのようなクラスで例外がいくつか見つかりますが、それらはすべて修正されているようです。誰かがこのようなものに出くわしましたか? 誰かがこれを機能させましたか?

4

2 に答える 2

11

いくつかのデバッグの後、これは JRE クラス ライブラリ、特にsun.net.www.protocol.http.HttpURLConnection.

HTTP エンドポイントと HTTPS エンドポイントの場合の HTTP 要求と応答を調査すると、成功した HTTP のケースでは要求にヘッダーProxy-Connection=keep-aliveがあり、失敗した HTTPS のケースでは欠落していることがわかりました。より一般的に読むと、「プロキシ接続」を使用するか、単に「接続」を使用するかについても混乱があるようです...

とにかく、HTTP の場合、コードが通過することは注目に値しますHttpURLConnection.writeRequests()。これには、次のコード スニペットが含まれます。

    /*
     * For HTTP/1.1 the default behavior is to keep connections alive.
     * However, we may be talking to a 1.0 server so we should set
     * keep-alive just in case, except if we have encountered an error
     * or if keep alive is disabled via a system property
     */

    // Try keep-alive only on first attempt
    if (!failedOnce && http.getHttpKeepAliveSet()) {
    if (http.usingProxy) {
        requests.setIfNotSet("Proxy-Connection", "keep-alive");
    } else {
        requests.setIfNotSet("Connection", "keep-alive");
    }

HTTPS のプロキシを介してトンネルを作成する場合、そのようなコードはありません。これにより、NTLM 認証の会話中に Squid が動揺します。

これを回避するためにHttpURLConnection.sendCONNECTRequest()、 に追加しました

if (http.getHttpKeepAliveSet()) {
    if (http.usingProxy) {
        requests.setIfNotSet("Proxy-Connection", "keep-alive");
    }
}

直前

setPreemptiveProxyAuthentication(requests);
http.writeRequests(requests, null);

HttpURLConnection.class「-Xbootclasspath/p」フラグを使用して変更した JRE を挿入したところ、動作するようになりました。正確にはエレガントではありませんが、これで終わりです。

于 2009-08-26T14:33:43.460 に答える
4

JAX-WS と結婚していますか? Commons httpclient を使用し、NTLM 認証が組み込まれている Apache Axis2 を使用しています。

例:

//Configure SOAP HTTP client to authenticate to server using NTLM
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();

//TODO make report server credentials configurable
auth.setUsername("jdoe");
auth.setPassword("strongpass");
auth.setDomain("WINDOWSDOMAIN");
auth.setHost("host.mydomain.com");
auth.setPort(443);

Options o = new Options();
o.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE,auth);
myWebServiceStub._getServiceClient().setOptions(o);
于 2009-08-25T14:34:46.483 に答える