使用SSL证书的PHP SOAP客户端

8
我正在尝试使用以下代码设置 Soap 客户端:
```php

我正在尝试使用以下代码设置Soap客户端:

```
<?php
$wsdl           = 'https://domain.com/?wsdl';
$endpoint       = 'https://domain.com';
$certificate    = dirname(__FILE__) . '/CertWithKey.pem';
$password       = 'pwd';

$options = array(
    'location'      => $endpoint,
    'keep_alive'    => true,
    'trace'         => true,
    'local_cert'    => $certificate,
    'passphrase'    => $password,
    'cache_wsdl'    => WSDL_CACHE_NONE
);

try {
    $soapClient = new SoapClient($wsdl, $options);
} catch(Exception $e) {
    var_dump($e);
}

我收到了一个.p12密钥文件和一个.crt证书文件。使用openssl,我将.p12文件转换为.pem文件,然后与.crt文件合并。CertWithKey.pem文件看起来很好,其中包含两个证书块。
无论我尝试做什么,我都会收到一个异常,消息是“SOAP-ERROR:Parsing WSDL:无法从'https://domain.com/?wsdl'加载:无法加载外部实体"https://domain.com/?wsdl"”。
在与远程方通话后,他们承认有一个请求进来,但他们记录了这个错误:“ssl握手被系统中断[hint:浏览器按下停止按钮?!]”。
由于我目前在网上没有找到任何有用的信息,所以我想请你们对此问题提供一些见解。
有什么建议可以尝试吗? 我正在运行PHP 5.3.8,并且服务器的IP地址已在远程方的防火墙中列入白名单。
3个回答

13

我解决了这个问题。考虑到有很多关于此问题的问题和不同的解决方案,其他人也会从这个解决方案中受益。以下是解决方法:

我使用openssl CLI程序将.p12密钥文件转换为.pem密钥文件。诀窍在于转换的方式。

首先,我使用以下命令进行转换,但出现了与问题描述相同的问题:

openssl pkcs12 -in key.p12 -out key.pem -nodes -clcerts

而下面的命令才是真正起作用的命令:

openssl pkcs12 -in key.p12 -out key.pem -clcerts

更多信息请参见我使用的资源:https://community.qualys.com/docs/DOC-3273


我也在尝试向服务器发送SOAP请求。我遇到了类似的问题,我的php应用程序无法与服务器通信,但是通过SOAP GUI可以正常工作。 我有一个.p12文件,我已经尝试将其转换为.pem文件并使用。当我创建SOAP客户端对象时,我会收到错误消息: SOAP-ERROR:解析WSDL:无法从https://<serverurl>?wsdl加载:无法加载外部实体https://<serverurl>?wsdl 请问这里出了什么问题? - Code Buster
如果您按照我的回答进行操作并成功合并了密钥和证书文件,则远程主机可能启用了防火墙并阻止了您的IP地址。否则,我无法确定问题的原因,建议您提出一个新问题来解决。 - Ben Fransen
我也遇到了同样的问题。我按照@Ben提供的确切步骤进行操作,使用提供的链接将p12转换为.pem格式。但是我仍然收到错误信息:curl: (58) Unable to load client cert -8018。 奇怪的是,我发现我提供的密码是三位数字“123”,而实际上我需要提供一个由6个字母组成的有效密码。 因此,我认为应该有一个良好长度的密码(不知道最小长度)。下一步缺失的是在SoapClient对象初始化中应提供'local_cert'和'passphrase'选项。 - Code Buster

0
        $mode = array(
            'soap_version' => 'SOAP_SSL_METHOD_SSLv2',  // use soap 1.2 client
            'trace' => 1,
            'stream_context' => stream_context_create(
            array(
                'ssl' => array(
                    'crypto_method' =>  STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
                    'verify_peer' => false,  // don't care about which company
                    'verify_peer_name' => false  // or company name
                    )   
                )
            )
        );

        $client = new SoapClient($x, $mode);

-1

相同的建议:

  1. 我使用SoapClient连接SSL服务,没有指定"endpoint" URL也可以正常工作。因此,我建议您尝试不使用此选项;

  2. php SoapClient有一个名为"ssl_method"的选项,您可以更改此协议的某些变体。如果您知道使用的协议,请尝试更改/指定此参数;

  3. 在参数列表中指定"verifypeer => false"和"verifyhost => false"。


感谢您的回复。 1: 我也尝试过不使用终端点,但是没有成功。2: 由于我的PHP版本,我无法使用ssl_method。3: 我错了还是verifypeer和verifyhost是未记录的参数(或者至少它们不在文档中:http://php.net/manual/en/soapclient.soapclient.php)。提供它们也没有任何区别。 - Ben Fransen
在参数列表中指定 "verifypeer => false" 和 "verifyhost => false",这意味着禁用安全性。这总是一个坏主意。 - Sander Visser
如果您查看 PHP SOAP 扩展的 C 源代码,您会发现 verifyhost 及 verifypeer 都不受支持,因此建议忽略这里的第三条建议。 - kguest
这个答案对我有用,需要额外的研究。那些提到的选项是在流上下文选项中设置的ssl选项。 - Randy Gamage

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接