【问题标题】:Java 6 NTLM proxy authentication and HTTPS - has anyone got it to work?Java 6 NTLM 代理身份验证和 HTTPS - 有人让它工作吗?
【发布时间】:2009-08-25 08:32:23
【问题描述】:

我有一个需要访问 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 的错误数据库会发现此类类中存在一些异常,但似乎都已修复。有没有人遇到过这样的事情?有没有人解决这个问题?

【问题讨论】:

  • 请也提供您的进口商品?

标签: java proxy jax-ws ntlm squid


【解决方案1】:

经过一些调试,这似乎是 JRE 类库中的一个缺陷,特别是在 sun.net.www.protocol.http.HttpURLConnection 中。

研究 HTTP 和 HTTPS 端点情况下的 HTTP 请求和响应表明,在成功的 HTTP 情况下,请求具有标头 Proxy-Connection=keep-alive,而在失败的 HTTPS 情况下则缺少该标头。更一般地阅读,似乎也应该使用“代理连接”还是只使用“连接”......

无论如何,值得注意的是,在HTTP情况下,代码通过HttpURLConnection.writeRequests(),其中包含以下代码sn-p

    /*
     * 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() 中添加了

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

就在之前

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

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

【讨论】:

  • 我遇到了同样的问题。我发现一个 JDK 错误描述了完全相同的问题:bugs.sun.com/view_bug.do?bug_id=6206466 奇怪的是,它被标记为重复/已修复,尽管另一个错误完全不同。
  • 是的,有时我不确定 Sun 的错误数据库是否让我想笑还是想哭。可能他们正忙于担心拉里·埃里森是否会解雇他们,以检查错误是否真的重复......
  • BigZig 能否请您也提供您的进口?
  • (几年后...)在错误报告中引用了这个问题:bugs.java.com/view_bug.do?bug_id=6973030 自 Java 7b109 以来已将其标记为已修复。
【解决方案2】:

您与 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);

【讨论】:

  • 这个项目离发布有点太近了,我无法接受删除 JAX-WS 并用一些东西替换它,但感谢您的建议。
猜你喜欢
  • 2010-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多