soapclient - php web service soap client
401 Autenticación Error cuando SoapClient intenta recuperar el archivo de esquema (2)
Mi aplicación se conecta de forma rutinaria a un servidor de terceros para obtener datos a través de SOAP / WSDL:
$this->soap_client = new SoapClient("https://[the-domain]:443/[path]?wsdl", array(
''trace''=>1,
''login''=>$this->username,
''password''=>$this->password,
''exceptions'' => true,
''cache_wsdl'' => WSDL_CACHE_NONE
)
Todo ha sido excelente durante el último año, pero recientemente actualizaron su archivo WSDL y ahora, cuando la aplicación intenta conectarse , recibo los siguientes dos errores :
SoapClient::SoapClient(http://[the-domain]:80/[path]?xsd=1): failed to open stream: HTTP request failed! HTTP/1.1 401 Unauthorized
y
SoapClient::SoapClient(): I/O warning : failed to load external entity "http://[the-domain]:80/[path]?xsd=1"
Cuando miro el archivo WSDL XML, parece que el archivo descargable ofensivo es el archivo de esquema del documento (schemaLocation) que está tratando de importar: (desde WSDL :)
<types>
<xsd:schema>
<xsd:import namespace="[irrelevant]" schemaLocation="http://[the-domain]:80/[path]?xsd=1"/>
</xsd:schema>
</types>
He estado golpeando mi cabeza contra esto por un tiempo, y hasta donde puedo decir, el problema es una de dos cosas:
- Cuando cargo esa URL de esquema en un navegador (después de la autenticación del navegador),
302 redirects
a una URLhttps
(y omite la declaración del puerto). ¿Es posible que la llamada SOAP no siga el redireccionamiento cuando se intenta importar el esquema? - Dado el hecho de que el mensaje de error es un error 401, ¿es posible que la llamada SOAP no esté transmitiendo credenciales al intentar importar el esquema? El archivo de esquema requiere la misma autenticación que el archivo WSDL, pero tal vez el servidor no amplíe la autenticación al esquema cuando intenta importar.
Asumiendo que es el segundo problema, ¿hay alguna manera de forzar al sistema a utilizar una URL de esquema diferente sin descargar el archivo WSDL, editarlo y almacenarlo / referenciarlo localmente? Si es así, podría intentar pasar las credenciales en la URL ( http://username:password@domain....
)?
Si mi única oportunidad es crear una copia modificada del archivo de esquema WSDL y XSD, que así sea, pero me encantaría saber si alguien tiene alguna idea que me permita evitar esto (ya que el esquema cambia con el tiempo). a tiempo).
Parece que PHP SoapClient se adhiere a la misma política de dominio (incluido el esquema) para enviar el nombre de usuario y contraseña de autenticación básica en la solicitud WSDL que se realiza para importar el archivo xsd en el esquema WDSL.
Entonces, si la url WSDL tiene un esquema https
y la importación tiene un esquema http
, PHP no envía la información de autenticación básica ya que la conexión ya no está encriptada cuando se solicita la URL de importación http
(lo que comprometería la confidencialidad de la información de autenticación).
Sin embargo, parece que al menos para algunas versiones de PHP (puede corregirse en versiones más nuevas) el problema de autenticación persiste incluso si la url http
redirecciona a la https
one (en el mismo dominio). Después del redireccionamiento a una URL segura con el mismo dominio, PHP podría incluir nuevamente la información de autenticación básica dada.
Solución
Al final, la única forma sencilla de solucionar esto fue hacer que la otra parte cambiara su contenido WSDL para importar una URL segura ( https
one) que tiene el mismo esquema, dominio y puerto que la url WDSL misma.
Solución
Si eso no es una opción para usted, por supuesto, siempre puede optar por la solución que es guardar el WSDL, así como las importaciones como archivos locales y consultar el archivo WDSL en lugar de la URL . Por supuesto, esto también significaría que tendría que cambiar el WSDL para importar el archivo local correcto (en lugar de la URL http
) y posiblemente otras importaciones también. Lamentablemente, esta es la única solución que conozco en este caso.
¿Error de PHP?
También encontré este informe de error de PHP que podría estar relacionado.
Le daría una oportunidad a cURL, tiene una opción para seguir las redirecciones