使用证书创建PHP SOAP请求

时间:2011-08-22 13:11:40

标签: php soap ssl https

我正在尝试创建一个到具有自签名证书的.NET Web服务的PHP SOAP连接,以便锁定服务以通过HTTPS进行通信。我继续得到错误,我不确定它是否与我创建证书的方式,我的Apache / PHP设置,我尝试建立SOAP请求的方式或其他方面有关。如果有人有任何指示,他们将不胜感激。提前谢谢。

证书生成

这就是我创建证书的方式。

  1. 创建受信任的根私钥:

      

    genrsa -out ca_authority_prv.pem 2048

  2. 创建受信任的根颁发机构证书:

      

    req -new -key ca_authority_prv.pem -x509 -out ca_authority_cert.pem

  3. 使证书颁发机构信任:

      

    x509 -in ca_authority_cert.pem -out ca_authority_trust.pem -trustout

  4. 退出OpenSSL并创建一个串行文件:

      

    echo 1000> ca_authority.srl

  5. 创建客户端私钥:

      

    genrsa -out Client_prv.pem 2048

  6. 创建客户端请求:

      

    req -new -key Client_prv.pem -out Client_req.pem

  7. 与CA签署客户请求:

      

    x509 -req -CA ca_authority_trust.pem -CAserial ca_authority.srl -CAkey ca_authority_prv.pem -in Client_req.pem -out Client_cert.pem

  8. 为客户端证书制作pfx

      

    pkcs12 -export -in Client_cert.pem -inkey Client_prv.pem -out Client_cert.pfx

  9. IIS安装程序

    创建此证书后,我按照相同的步骤获取服务器证书,并且:

    1. 将受信任的根CA添加到计算机受信任的根存储

    2. 将服务器证书添加到计算机商店

    3. 设置IIS以使用服务器证书并要求客户端证书

    4. PHP SOAP请求

      这是我用来建立PHP SOAP请求的代码(下面是错误):

      $wsdl = "https://localhost/MyService/MyService.asmx";
      $local_cert = "C:\\Certs\client_cert.pem";
      $passphrase = "openSaysMe";
      
          $soapClient = new SoapClient($wsdl, array('local_cert'=>  $local_cert,'passphrase'=>$passphrase));
          $theResponse = $soapClient->test();
      

      错误

      Warning: SoapClient::SoapClient() [soapclient.soapclient]: Unable to set private key file `C:\Certs\client_cert.pem' in C:\Program Files\Apache Group\Apache2\htdocs\soapWithAuth.php on line 53
      
      Warning: SoapClient::SoapClient() [soapclient.soapclient]: failed to create an SSL handle in C:\Program Files\Apache Group\Apache2\htdocs\soapWithAuth.php on line 53
      
      Warning: SoapClient::SoapClient() [soapclient.soapclient]: Failed to enable crypto in C:\Program Files\Apache Group\Apache2\htdocs\soapWithAuth.php on line 53
      
      Warning: SoapClient::SoapClient(https://localhost/MyService/MyService.asmx) [soapclient.soapclient]: failed to open stream: operation failed in C:\Program Files\Apache Group\Apache2\htdocs\soapWithAuth.php on line 53
      
      Warning: SoapClient::SoapClient() [soapclient.soapclient]: I/O warning : failed to load external entity "https://localhost/MyService/MyService.asmx" in C:\Program Files\Apache Group\Apache2\htdocs\soapWithAuth.php on line 53
      Error: SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://localhost/MyService/MyService.asmx'
      

      错误日志

      PHP Warning:  SoapClient::SoapClient() [<a href='soapclient.soapclient'>soapclient.soapclient</a>]: failed to create an SSL handle in C:\\Program Files\\Apache Group\\Apache2\\htdocs\\soapWithAuth.php on line 54
      

3 个答案:

答案 0 :(得分:14)

我设法让这个工作,但有一些奇怪的我想知道。特别是需要将客户端证书和私钥组合到单个文件中以与Soap请求以及证书密码短语一起发送,这打破了请求,尽管PHP Soap文档明确地将其作为选项包含在内。如果有人提出如何改进这一点,我很乐意听到。

1)创建OpenSsl客户端和服务器证书,并使用证书颁发机构对其进行签名。创建证书时不要为它们分配密码,只需在该点按Enter键即可。

2)将服务器证书颁发机构文件导入受信任根目录下的计算机证书存储区。您可以通过在命令提示符下使用MMC命令,然后添加“证书”管理单元来实现此目的。

3)将服务器证书导入机器商店个人证书存储区

4)在本地帐户个人存储中导入客户端证书。您可以通过在命令提示符下键入certmgr.msc来执行此操作。

5)确保让Apache运行SSL版本的PHP。如果您已经安装了非PHP版本的PHP,则可以按照以下步骤将Apache服务器配置为使用SSL运行。

httpd.conff

a) Remove the comment ‘#’ at line : LoadModule ssl_module modules/mod_ssl.so

b) Remove the comment ‘#’ at the line inside `<IfModule ssl_module>`:  Include /extra/httpd-ssl.conf

   and move this line after the block `<IfModule ssl_module>…. </IfModule>`  

php.ini

c) Remove the comment ‘;’ at the line which says: extension=php_openssl.dll

6)使用以下步骤配置IIS以使用证书和SSL:

a) Right click the 'Default Website' node choose 'Properties'

b) 'Directory Security' tab 'Server Certificate' button. Follow the wizard to select the certificate you imported into the store then complete the wizard and return to the 'Directory Security' tab.

c) Under 'Secure Communications' select the 'Edit' button. 

d) Check the 'Require Secure Channel (SSL) checkbox.

7)创建PHP SOAP请求(test()方法应该是Web服务中的有效方法):

$wsdl = "https://localhost/MyService/myservices.asmx?wsdl";
$local_cert = "C:\\SoapCerts\ClientKeyAndCer.pem";

$soapClient = new SoapClient($wsdl, array('local_cert' => $local_cert));

$theResponse = $soapClient->test();

8)将此文件放入Apache目录中。默认情况下:'C:\ Program Files \ Apache Group \ Apache2 \ htdocs'

9)您需要访问客户端证书。在生成客户端和服务器证书的步骤中,您还生成了私钥文件。打开client_prv.pem(客户端私钥文件)并使用文本编辑器将内容复制到新文档中。使用像Textpad这样的东西可能更安全,希望不会添加一堆特殊字符,证书解析器非常挑剔。私钥部分之后立即放置客户端证书(client_cer.pem)的内容,以便生成的文件是客户端私钥和客户端的未转义副本

证书。将生成的文件保存到您可以从php文件中获取的目录中。在上面的示例中,生成的文件是

'C:\ SoapCerts \ ClientKeyAndCer.pem'文件。

9)导航到localhost / nameOfYourFile.php。您应该看到与服务的成功连接,其响应与您的

的预期结果相匹配

Web服务方法。

答案 1 :(得分:1)

旁注:有一种方法可以使成功的SOAP请求 并使私钥和证书文件分开。为此,您必须创建一个流上下文并将其作为context选项传递:

  <?php

  $wsdl = "https://localhost/MyService/MyService.asmx";
  $context = stream_context_create(
    array(
     "ssl" => array(
     "local_cert" => "C:\\Certs\client_cert.pem",
     "local_pk"   => "/path/to/private/key"
      )
    )
  );

   $client = new \SoapClient($wsdl, array("context" => $context));

答案 2 :(得分:0)

GitBash

$ cd path/to/certificate/
$ openssl pkcs12 -in personal_certificate.pfx -out public_key.pem -clcerts

首先您必须输入一次 YOUR_CERT_PASSWORD,然后输入两次 DIFFERENT_PASSWORD!。后者可能可供所有有权访问代码的人使用。

PHP

<?php

$wsdlUrl   = "https://example.com/service.svc?singlewsdl";
$publicKey = "rel/path/to/certificate/public_key.pem";
$password  = "DIFFERENT_PASSWORD!";

$params = [
    'local_cert' => $publicKey,
    'passphrase' => $password,
    'trace' => 1,
    'exceptions' => 0
];

$soapClient = new \SoapClient($wsdlUrl, $params);

var_dump($soapClient->__getFunctions());
var_dump($soapClient->__getTypes());