Java 6 NTLM代理身份validation和HTTPS – 有没有人让它工作?

我有一个需要访问Web服务的Java应用程序(不是applet)。 已经使用JAX-WS生成了Web服务的代理,并且似乎工作正常。 在一种情况下,它需要通过Web代理服务器(实际上是Squid 3.0)进行通信,该服务器设置为需要NTLM身份validation。

在Sun的JRE 1.6.0_14上运行,一切都可以正常访问HTTP URL,而无需任何更改:内置的NTLM身份validation器启动,并且它都可以无效地运行。 但是,如果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数据库会在这些类中出现一些例外情况,但所有这些exception似乎都已得到修复。 有没有人遇到过这样的事情? 有人有这个工作吗?

经过一些调试,这似乎是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身份validation会话期间感到不安。

为了解决这个问题,我在HttpURLConnection.sendCONNECTRequest()添加了

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

就在此之前

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

我使用“-Xbootclasspath / p”标志将修改后的HttpURLConnection.class注入JRE,现在它可以工作了! 不完全优雅,但我们有。

你和JAX-WS结婚了吗? 我使用Apache Axis2,它使用公共httpclient并内置NTLM身份validation。

例:

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