Authentification de proxy Java 6 NTLM et HTTPS – Quelqu’un a-t-il réussi à le faire?

J’ai une application Java (et non une applet) qui doit accéder à un service Web. Les proxies du service Web ont été générés avec JAX-WS et semblent fonctionner correctement. Dans un scénario, il doit utiliser un serveur proxy Web (en réalité Squid 3.0), qui est configuré pour nécessiter une authentification NTLM.

Fonctionnant sur JRE 1.6.0_14 de Sun, tout fonctionne correctement pour accéder aux URL HTTP, sans aucune modification: l’authentificateur NTLM intégré s’active et tout fonctionne sans problème. Si, toutefois, l’URL du service Web est une URL HTTPS, l’appel du service Web échoue profondément dans le code de 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 

La recherche dans la firebase database de bogues de Sun révèle quelques exceptions dans ces classes, mais elles semblent toutes avoir été corrigées. Quelqu’un at-il rencontré quelque chose comme ça? Quelqu’un a-t-il cela au travail?

Après un débogage, cela semble être une faille dans les bibliothèques de classes JRE, en particulier dans sun.net.www.protocol.http.HttpURLConnection .

L’étude des demandes et des réponses HTTP dans les cas de points de terminaison HTTP et HTTPS a montré que, dans le cas HTTP réussi, les demandes avaient un en-tête Proxy-Connection=keep-alive , manquant dans le cas HTTPS défaillant. Plus généralement, il semble y avoir une certaine confusion sur le sharepoint savoir s’il faut utiliser “Connexion par proxy” ou simplement “Connexion”, aussi …

Quoi qu’il en soit, il est à noter que dans le cas HTTP, le code passe par HttpURLConnection.writeRequests() , qui contient l’extrait de code suivant.

  /* * 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"); } 

Il n’existe pas de code de ce type lors de la création d’un tunnel via le proxy pour HTTPS, ce qui a pour effet de bouleverser Squid lors de la conversation d’authentification NTLM.

Pour contourner ce HttpURLConnection.sendCONNECTRequest() , dans HttpURLConnection.sendCONNECTRequest() , j’ai ajouté

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

juste avant

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

HttpURLConnection.class mon HttpURLConnection.class modifié dans le JRE à l’aide de l’indicateur “-Xbootclasspath / p”, et cela fonctionne maintenant! Pas vraiment élégant, mais nous y sums.

Êtes-vous marié à JAX-WS? J’utilise Apache Axis2, qui utilise le httpclient commons et intègre l’authentification NTLM.

Exemple:

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