【问题标题】:PHP Soap ssl how to trust self-signed certificatePHP Soap ssl如何信任自签名证书
【发布时间】:2016-12-28 10:12:12
【问题描述】:

我正在用soap 为.net 中的web 服务创建一个php 客户端。 网络服务通过带有自签名证书的 https 运行,对于测试,我必须信任此证书而不安装它。

问题是我总是得到这个错误:

SOAP-ERROR:解析 WSDL:无法从“https://winsystemsintl.com:54904/PSAService.svc?wsdl”加载:无法加载外部实体“https://winsystemsintl.com:54904/PSAService.svc?wsdl”。

这是我的代码:

$opts = [
        'ssl' => [
            // set some SSL/TLS specific options
            'verify_peer' => false,
            'verify_peer_name' => false,
            'allow_self_signed' => true
        ],
         'http'=>[
            'user_agent' => 'PHPSoapClient'
        ]
    ];

    // Initialize Soap Client
    $this->client = new SoapClient($this->wsdl, array('ssl_method' => SOAP_SSL_METHOD_SSLv3,'soap_version' => SOAP_1_2,  'location' => 'https://winsystemsintl.com:54904/PSAService.svc','stream_context' => stream_context_create($opts), 'exceptions' => true, 'trace' => true));

我能够使用 wget 获取 wsdl:

wget --secure-protocol=SSLv3 https://winsystemsintl.com:54904/PSAService.svc?wsdl --no-check-certificate

希望有人能帮助我,非常感谢。

【问题讨论】:

    标签: php web-services ssl soap wsdl


    【解决方案1】:

    问题是 PHP 在下载 WSDL 文件时会忽略您的流上下文。一种解决方法是下载WSDL 文件,并将所有架构导入本地文件系统(我在这里使用tidy 来漂亮地打印XML):

    wget --secure-protocol=SSLv3 https://winsystemsintl.com:54904/PSAService.svc?wsdl --no-check-certificate -O - | tidy -xml -indent > PSAService.svc?wsdl
    wget --secure-protocol=SSLv3 https://winsystemsintl.com:54904/PSAService.svc?xsd=xsd0 --no-check-certificate -O - | tidy -xml -indent > PSAService.svc?xsd=xsd0
    wget --secure-protocol=SSLv3 https://winsystemsintl.com:54904/PSAService.svc?xsd=xsd1 --no-check-certificate -O - | tidy -xml -indent > PSAService.svc?xsd=xsd1
    wget --secure-protocol=SSLv3 https://winsystemsintl.com:54904/PSAService.svc?xsd=xsd2 --no-check-certificate -O - | tidy -xml -indent > PSAService.svc?xsd=xsd2
    wget --secure-protocol=SSLv3 https://winsystemsintl.com:54904/PSAService.svc?xsd=xsd3 --no-check-certificate -O - | tidy -xml -indent > PSAService.svc?xsd=xsd3
    

    接下来,您必须编辑 PSAService.svc?wsdl(wget 保存到的文件名)并将导入更改为指向您的本地系统而不是 Web。在您喜欢的编辑器中使用 replace-all 功能并将'https://winsystemsintl.com:54904/' 替换为'':

    示例 之前:

    <wsdl:types>
      <xsd:schema targetNamespace="http://tempuri.org/Imports">
        <xsd:import schemaLocation="https://winsystemsintl.com:54904/PSAService.svc?xsd=xsd0"
      namespace="http://tempuri.org/" />
        <xsd:import schemaLocation="https://winsystemsintl.com:54904/PSAService.svc?xsd=xsd1"
      namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
        <xsd:import schemaLocation="https://winsystemsintl.com:54904/PSAService.svc?xsd=xsd2"
      namespace="http://schemas.datacontract.org/2004/07/PSA.Service.MessageObjects.Pregunta" />
        <xsd:import schemaLocation="https://winsystemsintl.com:54904/PSAService.svc?xsd=xsd3"
      namespace="http://schemas.datacontract.org/2004/07/PSA.Service.MessageObjects.Respuesta" />
      </xsd:schema>
    </wsdl:types>
    

    之后:

    <wsdl:types>
      <xsd:schema targetNamespace="http://tempuri.org/Imports">
        <xsd:import schemaLocation="PSAService.svc?xsd=xsd0"
      namespace="http://tempuri.org/" />
        <xsd:import schemaLocation="PSAService.svc?xsd=xsd1"
      namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
        <xsd:import schemaLocation="PSAService.svc?xsd=xsd2"
      namespace="http://schemas.datacontract.org/2004/07/PSA.Service.MessageObjects.Pregunta" />
        <xsd:import schemaLocation="PSAService.svc?xsd=xsd3"
      namespace="http://schemas.datacontract.org/2004/07/PSA.Service.MessageObjects.Respuesta" />
      </xsd:schema>
    </wsdl:types>
    

    对每个下载的文件重复。

    接下来,将您的代码更改为以下内容(我假设所有 PHP/WSDL 文件都在同一个文件夹中):

    $opts = [
    'ssl' => [
      // set some SSL/TLS specific options
      'verify_peer' => false,
      'verify_peer_name' => false,
      'allow_self_signed' => true
    ],
      'http'=>[
        'user_agent' => 'PHPSoapClient'
      ]
    ];
    
    // Initialize Soap Client
    $client = new SoapClient('PSAService.svc?wsdl', array('ssl_method' => SOAP_SSL_METHOD_SSLv3,'soap_version' => SOAP_1_2,  'location' => 'https://winsystemsintl.com:54904/PSAService.svc','stream_context' => stream_context_create($opts), 'exceptions' => true, 'trace' => true));
    var_dump($client->__getFunctions());
    

    现在SoapClient 已跳过从网络下载WSDL,您已准备好开始使用您的流上下文进行呼叫。

    【讨论】:

    • 是的,确实如此,我绝对不会在生产环境中这样做,但如果开发人员需要使用自签名证书,它对测试目的很有用。
    • 哎呀,我无法编辑我以前的评论,这是评论的完整:嗨,克里斯,非常感谢您的回答,但现在我收到此错误“无法连接到主机”。我认为这可能是网络服务证书的问题,所以我与他们交谈,他们会给我生产网络服务的测试凭据来测试它,是的,我可以毫无问题地连接到生产网络服务......再次非常感谢.
    猜你喜欢
    • 2011-09-28
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 2021-01-09
    • 1970-01-01
    • 1970-01-01
    • 2015-11-02
    • 1970-01-01
    相关资源
    最近更新 更多