SoapClient尝试获取模式文件时出现401身份验证错误

Ben*_*n D 7 php xsd soap soap-client

我的应用程序通常连接到第三方服务器以通过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
)
Run Code Online (Sandbox Code Playgroud)

去年一切都很好,但他们最近更新了他们的WSDL文件,现在当应用程序尝试连接时,我收到以下两个错误:

SoapClient::SoapClient(http://[the-domain]:80/[path]?xsd=1): failed to open stream: HTTP request failed! HTTP/1.1 401 Unauthorized

SoapClient::SoapClient(): I/O warning : failed to load external entity "http://[the-domain]:80/[path]?xsd=1"

当我查看WSDL XML文件时,看起来违规的可卸载文件是它试图导入的文档模式文件(schemaLocation):( 来自WSDL :)

<types>
<xsd:schema>
<xsd:import namespace="[irrelevant]" schemaLocation="http://[the-domain]:80/[path]?xsd=1"/>
</xsd:schema>
</types>
Run Code Online (Sandbox Code Playgroud)

我已经打了一会儿反对这一点,据我所知,问题是两件事之一:

  1. 当我在浏览器中(在浏览器身份验证之后)将该架构URL加载302 redirectshttpsURL(并删除端口声明)时.尝试导入架构时,SOAP调用是否可能不遵循重定向?
  2. 鉴于错误消息是401错误 - 在尝试导入架构时SOAP调用是否可能没有传递凭据?模式文件需要与WSDL文件相同的身份验证,但是在尝试导入时服务器可能没有将身份验证扩展到模式?

假设这是第二个问题,有没有办法可以强制系统使用不同的架构URL而无需下载WSDL文件,编辑它,并在本地存储/引用它?如果是这样,我可以尝试传递URL(http://username:password@domain....)中的凭据?

如果我唯一的目的是创建WSDL和XSD模式文件的修改副本,那么就这样吧,但是我很想知道是否有人有任何想法可以让我避免这种情况(因为模式确实从时间变化 - 到时间).

Tom*_*avo 3

看起来 PHP SoapClient 坚持使用相同的域策略(包括方案)来在 WSDL 请求中发送基本身份验证用户名和密码,这是为了在 WDSL 架构中导入 xsd 文件。

因此,如果 WSDL url 有一个https方案并且导入有一个http方案,PHP 不会发送基本身份验证信息,因为请求导入 url 时连接不再加密http(这会损害身份验证信息的机密性)。

然而,似乎至少对于某些 PHP 版本(可能在较新版本中已修复),即使httpurl 重定向到该版本https(在同一域上),身份验证问题仍然存在。在重定向到具有相同域的安全 URL 之后,PHP 当然可以再次包含给定的基本身份验证信息。

解决方案

最后,我发现解决此问题的唯一巧妙方法是让对方更改其 WSDL 内容以导入安全 URL(https一个),该 URL 与 WDSL url 本身具有相同的方案、域和端口。

解决方法

如果这不是您的选择,您当然可以随时寻求解决方法,即将 WSDL 以及导入保存为本地文件,并引用 WDSL 文件不是URL。当然,这也意味着您必须更改 WSDL 以导入正确的本地文件(而不是 URL http),并且可能还需要更改其他导入。不幸的是,这是我所知道的在这种情况下的唯一解决方法。


PHP 错误?

我还发现了这个可能相关的PHP 错误报告。