MOSS 2007: 401.2 Unauthorized al invocar desde código JAVA el web service LISTS.asmx de SharePoint
Hola a todos.
¿Que tal estáis?
Me gustaría escribir sobre un caso curioso que he tenido hace poco.
Primero dejar claro que aunque como sabéis nosotros no soportamos código desarrollado en Java por nuestros clientes eso no significa que si el cliente nos lo pide ,y él es consciente de que a lo mejor no se puede llegar a una solución, podramos echarle una mano a identificar si el problema es de su código JAVA o un problema de interoperabilidad de su plataforma.
El cliente tenía una implementación en JAVA para llamar a un web service de SharePoint 2007 (concretamente List.asmx). Cada vez que la invocaba se encontraba con el siguiente error:
(401)Unauthorized
at org.apache.axis.transport.http.HTTPSender.readFromSocket(HTTPSender.java:744)
at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:144)
at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)
at org.apache.axis.client.Call.invokeEngine(Call.java:2784)
at org.apache.axis.client.Call.invoke(Call.java:2767)
at org.apache.axis.client.Call.invoke(Call.java:2443)
at org.apache.axis.client.Call.invoke(Call.java:2366)
at org.apache.axis.client.Call.invoke(Call.java:1812)
at com.microsoft.schemas.sharepoint.soap.ListsSoapStub.getListCollection(ListsSoapStub.java:1546)
at com.microsoft.schemas.sharepoint.test.Test.main(Test.java:56)
Como podíamos leer en el call stack de métodos parece que el problema poco tenía que ver con algún componente de MSFT. Éste lo encontrabamos a nivel del servidor SOAP para Web Services AXIS . También probamos con el framework de desarrollo IDE privativo de SAP SIBASE y obteniamos el mismo error pero con diferente call stack cuando cuando intentabamos añadir la referencia al web Service.
com.sybase.sup.tooling.xml.XmlException: java.io.IOException: Server returned HTTP response code: 401 for URL: https://url_cliente/_vti_bin/lists.asmx?wsdl
at com.sybase.sup.tooling.wsdl.WsdlParser.parseURL(WsdlParser.java:573)
at com.sybase.sup.tooling.wsdl.WsdlParser.parse(WsdlParser.java:68)
at com.sybase.uep.tooling.eis.WsEISOperationBuilder.<init>(WsEISOperationBuilder.java:91)
at com.sybase.uep.tooling.eis.WsEISOperationBuilder.<init>(WsEISOperationBuilder.java:66)
at com.sybase.uep.datasources.ws.views.WSConnection.initialize(WSConnection.java:154)
at com.sybase.uep.datasources.ws.views.WSConnection.<init>(WSConnection.java:38)
at com.sybase.uep.datasources.ws.views.WSConnectionFactory.createConnection(WSConnectionFactory.java:28)
at org.eclipse.datatools.connectivity.internal.ConnectionFactoryProvider.createConnection(Unknown Source)
at org.eclipse.datatools.connectivity.internal.ConnectionProfile.createConnection(Unknown Source)
at org.eclipse.datatools.connectivity.ui.PingJob.createTestConnection(Unknown Source)
at org.eclipse.datatools.connectivity.ui.PingJob.run(Unknown Source)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)
Caused by: java.io.IOException: Server returned HTTP response code: 401 for URL: https://url_cliente/_vti_bin/lists.asmx?wsdl
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1313)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
at com.sybase.sup.tooling.wsdl.WsdlParser.parseURL(WsdlParser.java:562)
... 11 more
La primera aproximación fue crear una aplicación .NET que consumiera el web service y comprobamos que funcionaba perfectamente, además de que el wsdl era browseable desde Internet Explorer.
Entonces el siguiente paso lógico ya que era un HTTP ERROR 401.2 - Unauthorized:Access is denied to server configuration fue comprobar cual era su método de authenticación en SharePoint. Se vió que era NTLM entonces se procedió a probar con anónima y básica. En estas dos anteriores funcionó perfectamente pero había algo con la NTLM que hacía que fallara.
Reportado en un caso no soportado, un compañero comentaba que el problema esta en la creación del NTLM hash por parte de AXIS pero éste quedó sin solución. Para lo cual después de un poco de investigación por BING me topé con los siguientes enlaces:
Using NTLM Authentication in an Axis web service client
I haven't tried doing this, but apparently you can have your Axis client use Windows NTLM authentication by telling the client-config.wsdd file to use "CommonsHTTPSender" instead of just plain "HTTPSender" as the http transport. Do a Google search for "NTLM and CommonsHTTPSender" for more detail.
https://www.nsftools.com/stubby/ApacheAxisClientTips.htm
NTLM from an Axis (SOAP) service client - in 3 steps
https://dev-answers.blogspot.com/2011/03/ntlm-from-axis-soap-service-client-in-3.html
https://thejavablog.wordpress.com/2009/04/15/0null/
Finalmente cambiamos el client-config.wsdd:
<transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"/>
por:
<transport name="http" pivot="java:org.apache.axis.transport.http.CommonsHTTPSender" />
Al final con otros cambios menores en el código todo funcionó correctamente.
Muchas Gracias a todos.
Héctor Calvarro Martín. SharePoint Dev. Microsoft Support Engineer for DEV EMEA