使用SoapClient连接https主机时,如何解决SSL问题?

12

TLDR

The author is having trouble connecting to a SOAP server through HTTPS/SSL using a PHP SoapClient. They suspect the issue is with the SSL connection and have tried various solutions without success.

complete

The author is attempting to connect to a SOAP server via HTTPS using a PHP SoapClient, but is encountering "Could not connect to host" errors. They believe the problem lies with the SSL connection, as they are able to reach another server using the same connection method. The author has tried various solutions, including creating a stream_context for the WSDL options, but has not had success.

Situation

  • The author is creating a PHP SoapClient based on a local WSDL.
  • Changing the endpoint results in successful request and response headers.
  • The machine is reachable from their server, but there is an SSL connection issue when using wget or openssl to connect.

What I tried.

The author has attempted various suggested solutions for similar issues, but without success. This includes creating a stream_context for the WSDL options.

$context = stream_context_create(
              array(
                'ssl' => array(
                           'verify_peer' => false,  //default
                           'allow_self_signed' => true, //needs verify peer, tried that
                           'ciphers'=>"SHA1", // quite random.
                   ),
                'https' => array(
                           'curl_verify_ssl_peer'  => false,
                           'curl_verify_ssl_host'  => false
                          )
      )
            );
$options['stream_context'] = $context;

首先,只使用 verify_peerallow_self_signed 选项的 ssl。然后我添加了 https 数组,最后我在 ssl 中添加了 ciphers 键。

我找到了对 这个 bug 的参考,但是1)我没有收到那个警告,2)它似乎与代理有关,3)我的版本不应该再有这个 bug。我正在运行 php 5.3.10

当我尝试使用 wget 获取 URL 时,我得到:

    wget https://[[servername]]/SOAP
    Resolving [[servername]] ([[servername]])... xxx.xxx.xxx.xxx
    Connecting to [[servername]]([[servername]])|xxx.xxx.xxx.xxx|:443... connected.
    OpenSSL: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
如果我尝试使用openssl连接,我会得到这个:
$ openssl s_client -connect [[server]]:443 -state
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:unknown state
SSL3 alert read:fatal:handshake failure
SSL_connect:error in unknown state
3074463944:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:724:

但是如果我强制使用 SSL3,就会得到预期的结果。

$ openssl s_client -ssl3 -connect [[server]]:443 -state
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv3 write client hello A
SSL_connect:SSLv3 read server hello A
**happy certificate stuff. this is good**
Protocol  : SSLv3
Cipher    : DHE-RSA-AES256-SHA
**more happy certificate stuff. **

我尝试添加 这个问题 中设置 ssl_version 为 3 的 curl-wrapper(因为似乎在上面的 openssl 命令中可以工作)。但是该包装器会放弃一些参数,因此我不确定这会有多完整。此外,除非我明确将检查设置为 false,否则仍会出现握手错误。如果我这样做(见下文),我将获得一个空响应。

curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);

原因

如上所述,我怀疑是ssl握手问题,但我不知道该如何解决。我并不怀疑wsdl或客户端创建存在问题,因为连接使用另一个wsdl、相同的wsdl和不同位置设置等都可以正常工作。纯粹是这个(https)端点让我感到头痛。

额外测试

就像上面用curl包装器进行的测试一样,我尝试发送一个最小的soap信封,如@halfwarr在评论中建议的那样。也返回了空响应。

因此,看起来我确实有一种方法可以从服务器中挤出一个http 204,但这几乎不能算是成功。但它可能是第二个问题吗?不确定。

我想我需要尝试强制使用ssl3,但我不知道如何做到这一点(而且这可能也是错误的路径,所以我在这里尽力避免XY问题 :)


我不确定,但是尝试一下5.4.x版本是否值得,以防您的PHP版本存在问题? - halfer
不完全是。现在,生产环境不会那么快朝这个方向发展。目前这个版本还受到支持,所以我不认为会有问题(而且请看我刚刚添加的openssl内容:我认为那仍然是问题所在) - Nanne
你已经在你的系统上配置了SSL吗? - Rahul11
你指的是什么?正如你在问题中所看到的,如果我指定“-ssl3”,我可以让openssl连接,但如果不指定,则无法连接。我怀疑这也是php的SoapClient面临的问题,但我不确定。 - Nanne
你尝试过使用cURL发送SOAP信封的XML并查看结果吗?(https://dev59.com/3XA75IYBdhLWcg3w9-Ox)我认为这将为您提供一种简单的方法来测试SSL选项,而无需处理扩展soapClient和可能引入的其他问题。 - Halfwarr
嗯,有趣的观点!明天我会第一时间尝试这个! - Nanne
3个回答

1

最新版本的 PHP 5.5.3 可以让你设置 SSL 版本。我见过其他人能够使用 stream_context,但我也无法使其工作。

作为一种解决方法和故障保护,我使用了一个 catch 来获取 SOAP 请求信封(类似于上面你测试过的内容):

$xml = $client->__getLastRequest()

并通过curl发送:


curl_setopt($ch, CURLOPT_SSLVERSION, 3);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

这让我至少能够继续前进。

1
有趣。尝试添加这个:
wget https://[[SERVER]]/soap/ —post-file=request.xml —header=”Content-Type: text/xml” -O response.xml

这将把结果保存为名为response.xml的文件。

1
我可能没有表达清楚,但重点是让SoapClient连接,wget只是为了展示问题可能出在哪里。我会在问题中稍作调整。 - Nanne
https://drupal.org/node/880862 - Matheno

0

我之前没有特别提到,但是我正在使用Linux :) - Nanne

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