简体   繁体   English

使用证书创建 PHP SOAP 请求

[英]Creating a PHP SOAP request with a certificate

I am attempting to create a PHP SOAP connection to a .NET Web Service that has a self-signed certificate in order to lock down the service for communication over HTTPS.我正在尝试创建到具有自签名证书的 .NET Web 服务的 PHP SOAP 连接,以便锁定该服务以通过 HTTPS 进行通信。 I continue to get error's and I'm not sure if it has something to do with the way I create the certificate, my Apache/PHP setup, the way I attempt to establish the SOAP request or something else.我继续遇到错误,我不确定它是否与我创建证书的方式、我的 Apache/PHP 设置、我尝试建立 SOAP 请求的方式或其他方式有关。 If anyone has any pointers they will be greatly appreciated.如果有人有任何指示,他们将不胜感激。 Thanks in advance.提前致谢。

Certificate Generation证书生成

This is how I am creating the certificate.这就是我创建证书的方式。

  1. Create the trusted root private key:创建受信任的根私钥:

    genrsa -out ca_authority_prv.pem 2048 genrsa -out ca_authority_prv.pem 2048

  2. Create the trusted root authority cert:创建受信任的根权限证书:

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

  3. Make the cert authority trusted:使证书颁发机构受信任:

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

  4. Exit OpenSSL and create a serial file:退出 OpenSSL 并创建一个串行文件:

    echo 1000 > ca_authority.srl回声 1000 > ca_authority.srl

  5. Create the client private key:创建客户端私钥:

    genrsa -out Client_prv.pem 2048 genrsa -out Client_prv.pem 2048

  6. Create the client request:创建客户端请求:

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

  7. Sign the client request with the CA:使用 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 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. Make the pfx for the client cert为客户端证书制作 pfx

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

IIS Setup IIS 设置

Once this certificate is created I follow the same steps for a server certificate and:创建此证书后,我将对服务器证书执行相同的步骤,并且:

  1. Add the trusted root CA to the Machine Trusted Root Store将受信任的根 CA 添加到机器受信任的根存储

  2. Add the server certificate to the machine store将服务器证书添加到机器存储

  3. Setup IIS to use the server certificate and require client certificates设置 IIS 以使用服务器证书并需要客户端证书

PHP SOAP Request PHP SOAP 请求

This is the code I am using to establish the PHP SOAP request (below is the error):这是我用来建立 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();

ERROR错误

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'

ERROR LOG错误日志

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

I managed to get this working but there are some oddities that I wonder about.我设法让这个工作,但有一些我想知道的奇怪之处。 Specifically the need to combine the client certificate and private key into a single file to send along with the Soap Request as well as the certificate pass-phrase was breaking the request although the PHP Soap documentation explicitly includes it as an option.特别是需要将客户端证书和私钥组合到一个文件中以与 Soap 请求以及证书密码短语一起发送,这破坏了请求,尽管 PHP Soap 文档明确将其作为一个选项包含在内。 If anyone has input on how to improve this I would love to hear it.如果有人对如何改进这一点有意见,我很乐意听到。

1) Create the OpenSsl client and server certificates and sign them with the certificate authority. 1) 创建 OpenSsl 客户端和服务器证书,并使用证书颁发机构对其进行签名。 When creating the certificate do not assign a passphrase to them, just hit the enter button at that point.创建证书时不要为它们分配密码,只需在此时按下 Enter 按钮即可。

2) Import the server certificate authority file into the Machine certificate store under the trusted root. 2) 将服务器证书颁发机构文件导入受信任根下的 Machine 证书库中。 You can get to this by using the MMC command at the command prompt and then adding the Certificates snap in.您可以通过在命令提示符下使用 MMC 命令然后添加证书管理单元来实现这一点。

3) Import the Server certificate into the Machine store Personal certificate store 3)将Server证书导入Machine store Personal证书存储

4) Import the client certificate in the local account Personal store. 4) 在本地账户个人存储中导入客户端证书。 You can do this by typing certmgr.msc at the command prompt.您可以通过在命令提示符下键入 certmgr.msc 来执行此操作。

5) Make sure to have Apache with a SSL version of PHP running. 5) 确保运行带有 SSL 版本的 PHP 的 Apache。 If you already had a non-php version of PHP installed you can follow these steps to configure your Apache server to run using SSL.如果您已经安装了非 php 版本的 PHP,您可以按照以下步骤配置您的 Apache 服务器以使用 SSL 运行。

Inside httpd.conffhttpd.conf里面

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>`  

Inside php.iniphp.ini里面

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

6) Configure IIS to use a certificate and SSL using the following steps: 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) Creating the PHP SOAP request (the test() method should be a valid method in your Web service): 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) Place this file into your Apache directory. 8) 将此文件放入您的 Apache 目录中。 By Default: 'C:\\Program Files\\Apache Group\\Apache2\\htdocs'默认:'C:\\Program Files\\Apache Group\\Apache2\\htdocs'

9) You will need access to the client certificate. 9) 您将需要访问客户端证书。 In the steps you took to produce the client and server certificates you also produced the private key files.在您生成客户端和服务器证书的步骤中,您还生成了私钥文件。 Open the client_prv.pem (the client private key file) and copy the contents into a new document with a text editor.打开 client_prv.pem(客户端私钥文件)并使用文本编辑器将内容复制到新文档中。 It is probably safer to use something like Textpad that will hopefully not add a bunch of special characters, certificate parsers are very picky.使用像 Textpad 这样的东西可能更安全,它希望不会添加一堆特殊字符,证书解析器非常挑剔。 Immediately after the private key part place the contents of the client certificate (client_cer.pem) so that the resulting file is an un-escaped copy of the client private key and client在私钥部分之后立即放置客户端证书 (client_cer.pem) 的内容,以便生成的文件是客户端私钥和客户端的未转义副本

certificate.证书。 Save the resulting file to a directory you can get to from the php file.将生成的文件保存到您可以从 php 文件访问的目录中。 In the example above the resulting file is the在上面的例子中,结果文件是

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

9) Navigate to localhost/nameOfYourFile.php. 9) 导航到 localhost/nameOfYourFile.php。 You should see a successful connection to the service with a response matching the expected results from your您应该看到与服务的成功连接,其响应与您的预期结果相匹配

Web service method.网络服务方法。

A side note: there is a way to make successful SOAP request and keep the private key and certificate file separated.旁注:有一种方法,使成功的SOAP请求,并保持私钥和证书文件分开。 To do this, you have to create a stream context and pass that as the context option:为此,您必须创建一个流上下文并将其作为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));

GitBash gitbash

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

First you have to enter YOUR_CERT_PASSWORD once, then DIFFERENT_PASSWORD!首先您必须输入YOUR_CERT_PASSWORD一次,然后输入DIFFERENT_PASSWORD! twice.两次。 The latter will possibly be available to everyone with access to code.可以访问代码的每个人都可以使用后者。

PHP 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());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM