Soap客户端调用SSL

时间:2013-01-16 13:59:50

标签: php zend-framework soap ssl

我正在尝试从HTTPS服务器获取WSDL的内容

<?php
echo file_get_contents("https://zendsoap.lan/Zend_Soap_Server.php?wsdl");
?>

它回归:

警告:file_get_contents()[function.file-get-contents]:SSL操作失败,代码为1. OpenSSL错误消息:错误:1408E0F4:SSL例程:func(142):/ Applications / AMPPS中的reason(244)第4行/www/zendSoap.lan/Zend_Soap_Client.php

警告:file_get_contents()[function.file-get-contents]:无法在第4行的/Applications/AMPPS/www/zendSoap.lan/Zend_Soap_Client.php中启用加密

警告:file_get_contents(https://zendsoap.lan/Zend_Soap_Server.php?wsdl)[function.file-get-contents]:无法打开流:/Applications/AMPPS/www/zendSoap.lan/中的操作失败第4行的Zend_Soap_Client.php

当我可以转到WSDL位置时(https://zendsoap.lan/Zend_Soap_Server.php?wsdl):一切都很好。

P.S:有谁能告诉我如何共享WSDL文件

3 个答案:

答案 0 :(得分:3)

我同意RockyFord关于它是一个SSL问题(我很确定你会有一个自签名证书,并且由于使用SSL,你需要采取一些步骤来减少安全问题) 。关于直接问题,您可以尝试使用与此类似的代码修复它:

$url = 'https://zendsoap.lan/Zend_Soap_Server.php?wsdl';

$contextOptions = array(
    'ssl' => array(
        'verify_peer' => true,
        'CN_match'    => 'zendsoap.lan' // assuming zendsoap.lan is the CN used in the certificate
    )
);

$sslContext = stream_context_create($contextOptions);

$wsdlContent = file_get_contents($url, NULL, $sslContext);

更新: 将上面的代码更改为

似乎是一个简单的解决方案
 'verify_peer' => false

虽然它可能适用于基本开发,但它并不是一个好主意,绝对不应该在生产环境中使用,因为它引入了严重的安全问题 - 请参阅How to properly secure remote API calls over SSL from PHP code by Artur Ejsmont上的这篇优秀文章了解更多信息关于此主题以及OWASP的Transport Layer Security Cheat SheetSecuring Web Services

要了解有关在Zend Framework应用程序中共享WSDL的观点,您可以执行以下操作来开始:

// go to application/configs/application.ini
// if your APPLICATION_ENV is development then add the following line in the development section:
phpSettings.soap.wsdl_cache_enabled = 0

上面的行将阻止您的wsdl在开发过程中被缓存。接下来,您可能想要创建一个SoapController并添加如下所示的操作:

public function serverAction()
{
    $baseUrl = 'http://zendsoap.lan/soap/server';

    if( isset( $_GET['wdsl'] ) ) {
        $strategy = new Zend_Soap_Wsdl_Strategy_AnyType();
        $server = new Zend_Soap_AutoDiscover($strategy);
        $server->setUri($baseUrl);
        $server->setClass('Application_Model_Web_Service');
        $server->handle();
    } else {            
        $server = new Zend_Soap_Server($baseUrl . '?wsdl');
        $server->setClass('Application_Model_Web_Service');
        $server->handle();
    }
}

上述方法的优点是将动态生成WSDL。您将注意到将调用setClass()方法,并将'Application_Model_Web_Service'作为唯一参数传递。要测试您的配置,我建议您创建该类并插入以下方法。使用包含单一方法的简单服务测试配置将帮助您在使服务更复杂之前进行故障排除。以下是示例方法:

// Note: you should definitely comment your methods correctly in the class so 
// the WSDL will be generated correctly - by that I mean use @param and @return
// so the correct input and output types can be determined and added to the WSDL
// when the the ZF component generates it for you
/**     
 * @return string
 */
 public function getMessage()
 {
     return 'ok';
 }

更新: 也是为了回答您提出的有关使用 Zend_Soap_Client 访问网络服务的问题,因为看起来您打算制作它是一个安全的服务我建议你提出一个单独的问题,关于使用php建立安全的肥皂服务。如果你解释更多关于你在这个问题上想要做什么,你可能会得到一些最好的专家的一些好的意见做法: - )

我知道你是新来的,所以如果你对答案感到满意,你可以接受它,一般来说,最好只回复一个答案,而不是添加另一个回答答案。当你知道当然如何,当有人告诉你时更容易;-)

答案 1 :(得分:0)

我尝试了定义Soap Server的方式,唯一的事情是我使用自定义类而不是使用Application_Model_Web_Service。我正在为客户端使用单个文件。服务器。如果我在没有?wsdl的情况下运行https://zendsoap.lan/Zend_Soap_Server.php,则会产生以下结果:

<SOAP-ENV:Envelope>
 <SOAP-ENV:Body>
  <SOAP-ENV:Fault>
   <faultcode>WSDL</faultcode>
  <faultstring>SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://zendsoap.lan/Zend_Soap_Server.php?wsdl' : failed to load external entity "https://zendsoap.lan/Zend_Soap_Server.php?wsdl"
  </faultstring>
  </SOAP-ENV:Fault>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

当我按照你说的方式尝试file_get_contents()时,我明白了:

Warning: file_get_contents() [function.file-get-contents]: SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:func(144):reason(134) in /Applications/AMPPS/www/zendSoap.lan/https_soap_test.php on line 16

Warning: file_get_contents() [function.file-get-contents]: Failed to enable crypto in /Applications/AMPPS/www/zendSoap.lan/https_soap_test.php on line 16

Warning: file_get_contents(https://zendsoap.lan/Zend_Soap_Server.php?wsdl) [function.file-get-contents]: failed to open stream: operation failed in /Applications/AMPPS/www/zendSoap.lan/https_soap_test.php on line 16

以下是我的证书截图的链接: http://i.stack.imgur.com/bKoVD.png

感谢您的帮助。

答案 2 :(得分:0)

问题解决了改变'verify_peer'=&gt;假

如果我在没有file_get_contents()的情况下使用Zend_Soap_Client,请(@dkcwd)告诉我代码应该是什么。我的意思是有任何我在互联网上找不到的选项来做'verify_peer'=&gt;假的。

感谢@dkcwd

更新:让我总结一下我在做什么,我正在尝试通过SSL创建一个基本的SOAP服务器。在我的生产网站上提供Web服务之前,我必须在具有自签名证书的开发系统上进行测试(现在认证是一个问题)。 以下是我在这方面遇到的问题:

  1. 当我尝试调用https://zendsoap.lan/Zend_Soap_server.php?wsdl时,我可以查看wsdl。
  2. 但是当我尝试https://zendsoap.lan/Zend_Soap_server.php时,我明白了:

    SOAP-ERROR:解析WSDL:无法从'https://zendsoap.lan/Zend_Soap_Server.php?wsdl'加载:无法加载外部实体“https://zendsoap.lan/Zend_Soap_Server.php?wsdl “ 这是我应该

  3. 我在启动服务器上运行verify_peer =&gt; false的原因,因此无需验证我自己创建的证书,但显然在生产中我希望验证证书。
  4. 这个东西适用于NuSoap,但NuSoap中的大部分内容都不推荐使用运行PHP 5.4.6的服务器,所以对我来说使用PHP的SOAP扩展是最可靠的解决方案。我使用 Zend 的原因是我们正在将我们的系统从一些第三方框架转移到Zend Framework,而且我每天都会收到来自客户端的请求来添加这个&amp;我假设,如果我使用Zend库开发客户端的每个新请求,那么在后期阶段我将很容易转移到Zend Framework。

    我希望我在那里有所了解。

    非常感谢提前......