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

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







当我查看WSDL XML文件时,似乎有问题的可卸载文件是它尝试导入的文档架构文件(schemaLocation):(从WSDL :)
<types>
<xsd:schema>
<xsd:import namespace="[irrelevant]" schemaLocation="http://[the-domain]:80/[path]?xsd=1"/>
</xsd:schema>
</types>

我一直对此表示怀疑,据我所知,问题是两件事之一:
  • 当我在浏览器中加载该架构URL时(在浏览器认证之后),它将302 redirects转换为https URL(并删除端口声明)。尝试导入模式时,SOAP调用是否可能不遵循重定向?
  • 给定错误消息是401错误的事实-尝试导入模式时,SOAP调用是否可能没有传递凭据?模式文件需要与WSDL文件相同的身份验证,但是服务器在尝试导入时是否未将身份验证扩展到模式?

  • 假设这是第二个问题,是否有任何方法可以强制系统使用其他架构URL,而无需下载WSDL文件,对其进行编辑以及将其存储/本地引用呢?如果是这样,我可以尝试在URL(http://username:password@domain....)中传递凭据吗?

    如果我唯一的想法是创建WSDL和XSD模式文件的修改后的副本,就可以了,但是我很想听听是否有人有让我避免这种想法的想法(因为模式确实会随着时间而改变-时间)。

    最佳答案

    看起来PHP SoapClient坚持使用same domain policy(包括方案)在WSDL请求中发送基本身份验证用户名和密码,此操作是在WDSL模式中导入xsd文件的。

    因此,如果WSDL URL具有https方案,而导入具有http方案,则PHP将不发送基本身份验证信息,因为在请求http导入URL时连接不再加密(这将损害身份验证信息的 secret 性)。

    但是,似乎至少对于某些PHP版本(在新版本中可能已修复),即使http url重定向到https一个(在同一域上),身份验证问题仍然存在。在重定向到具有相同域的安全URL后,PHP可能会偏离路线,再次包含给定的基本身份验证信息。

    解决方案

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

    解决方法

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

    PHP Bug?

    我也发现了这个PHP bug report可能与之有关。

    10-07 12:06