2009-08-25 46 views
11

我有一個需要訪問Web服務的Java應用程序(不是小程序)。 Web服務的代理已經使用JAX-WS生成,似乎工作正常。在一種情況下,它需要通過Web代理服務器(實際上是Squid 3.0)進行通信,該服務器需要NTLM身份驗證。Java 6 NTLM代理身份驗證和HTTPS - 任何人都可以使用它?

運行在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的bug數據庫變成了在這樣的類有一些例外,但他們似乎已經修復。有沒有人遇到過這樣的事情?有沒有人得到這個工作?

+0

請提供您的進口呢? – itro 2012-01-24 13:02:54

回答

4

你是娶了JAX-WS?我使用Apache Axis2,它使用公共httpclient並具有內置的NTLM身份驗證。

實施例:

//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); 
+2

這個項目對我來說太近了一點,因爲我很樂意將JAX-WS取代並用一些東西代替它,但是謝謝你的建議。 – DavidK 2009-08-26 07:37:30

10

一些調試之後,這似乎是在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,從而導致squid NTLM身份驗證對話期間生氣的隧道時,有沒有這樣的代碼。

要解決這個問題,在HttpURLConnection.sendCONNECTRequest(),我只是

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

我注入前加入

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

我修改HttpURLConnection.class到JRE使用 「-Xbootclasspath/P」 標誌,而現在有用!不完全優雅,但我們是。

+1

我遇到同樣的問題。我發現了一個JDK錯誤恰好說明了同樣的問題:http://bugs.sun.com/view_bug.do?bug_id=6206466 奇怪的是,它被標記爲重複/固定的,雖然其他錯誤是完全不同的。 – sereda 2010-01-16 11:11:28

+2

是的,有時我不確定Sun的錯誤數據庫是否讓我想笑或哭。可能他們太忙擔心,如果拉里·埃裏森是要解僱他們或不檢查錯誤是否真正複製... – DavidK 2010-01-21 21:58:21

+1

BigZig請你過你提供進口? – itro 2012-01-24 13:06:42