简体   繁体   English

PHP CURL和SSL证书(或证书链)

[英]PHP CURL and SSL certificate (or cert chain)

Good day! 美好的一天!

I've REST API which is accessible via SSL (https://). 我有REST API,可通过SSL(https://)访问。 I'd like to put correct cert (or cert chain) along with my scripts written PHP and CURL to make request. 我想将正确的证书(或证书链)以及编写为PHP和CURL的脚本一起提出请求。

Here are how certs from my target ( http://api.vkontakte.ru ) look like in Firefox: 这是我的目标( http://api.vkontakte.ru )中的证书在Firefox中的外观:

http://speedcap.net/img/bc687485819715c65d6fe1e4ca1fdc40/1a2be.png http://speedcap.net/img/bc687485819715c65d6fe1e4ca1fdc40/1a2be.png

Here is a snippet from saved "cert chain X.509 in PEM format" from Firefox (described here: http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/ ): 这是来自Firefox的已保存“ PEM格式的证书链X.509”的摘录(在此处进行了描述: http//unitstep.net/blog/2009/05/05/using-curl-in-php-to-access- https-ssltls-protected-sites / ):

-----BEGIN CERTIFICATE-----
MIIFVzCCBD+gAwIBAgIHKx5Ov2FOejANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
[..skip...]
0npsf5fkvT8E13NgVY0PK6V/baMTlTgWXKQZ
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx
[..skip...]
qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV
U+4=
-----END CERTIFICATE-----

Here is code example of CURL init: 这是CURL init的代码示例:

$this->ch = curl_init();
    curl_setopt_array($this->ch, array(

        CURLOPT_TIMEOUT => 30,
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_AUTOREFERER => TRUE,
        CURLOPT_FOLLOWLOCATION => TRUE,

        CURLOPT_SSL_VERIFYPEER => TRUE,
        CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_CAINFO => <path to my cert>,        
    )); 

I've got CURL error 60 ( CURLE_SSL_CACERT ) complaining about wron cert. 我有CURL错误60( CURLE_SSL_CACERT )抱怨wron证书。

What I've tried: 我尝试过的:

  • I've verified that my cert file is used, because when I specify wrong path it complains that it can't find cert (error 70) 我已验证使用了我的证书文件,因为当我指定错误的路径时,它会抱怨找不到证书(错误70)

  • I've checked with Facebook SDK and their cert chain that my CURL works with such setup 我已经与Facebook SDK及其证书链进行了核对,证明我的CURL可用于此类设置

  • I've tried to export different chains (including or excluding) last cert in chain 我试图导出不同的链(包括或不包括)链中的最后一个证书

  • Tried CURLOPT_SSL_VERIFYHOST => 1 . 尝试过CURLOPT_SSL_VERIFYHOST => 1

Any ideas are welcome! 欢迎任何想法!

Vkontakte moved from vkontakte.ru domain to vk.com few years ago. 几年前,Vkontakte从vkontakte.ru域名移至vk.com。 And they change their api handler url too. 他们也更改了自己的api处理程序网址。 This is my solution: 这是我的解决方案:

  1. Open https://vk.com/ in firefox 在firefox中打开https://vk.com/
  2. Export cert chain as X.509 for this site 将此站点的证书链导出为X.509
  3. Change target url from http://api.vkontakte.ru to https://api.vk.com/ 将目标网址从http://api.vkontakte.ru更改为https://api.vk.com/

This is my code with curl options: 这是我的带有curl选项的代码:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CAINFO, getcwd() ."/ffchainvk.crt"); //  ok

Where ffchainvk.crt is file with exported cert chain. 其中ffchainvk.crt是带有导出证书链的文件。

Curl uses CA certificates in a separate location on the server than what the rest of the system, like a desktop would. Curl在服务器上与系统其余部分(如台式机)不同的位置使用CA证书。 I have had to install CA certificates into the filesystem before. 我之前必须将CA证书安装到文件系统中。 PHP libcurl will use the libraries that the command line utility uses as well. PHP libcurl将使用命令行实用程序也使用的库。 Please see http://curl.haxx.se/docs/sslcerts.html . 请参阅http://curl.haxx.se/docs/sslcerts.html

These are the steps that appear to work: 这些步骤似乎起作用:

  1. Visit the https url in firefox 在firefox中访问https网址
  2. Click the green bar, click the arrow, then "more information" 单击绿色栏,单击箭头,然后单击“更多信息”。
  3. Click "View Certificate" then click "details" tab at the top 单击“查看证书”,然后单击顶部的“详细信息”选项卡
  4. Then click each level and export every certificate: 然后单击每个级别并导出每个证书:

    Root CA 根CA

    Server CA and 服务器CA

    example-website.invalid . example-website.invalid

    You should save all three files to your computer. 您应该将所有三个文件保存到计算机。 Copy all three files into a single file, eg custom_name_cert.pem 将所有三个文件复制到一个文件中,例如custom_name_cert.pem

Copy that pem file into a directory that is accessible with PHP, ideally the file has permissions 644. You might even go for 444 to prevent tampering, and change it to 644 when you need to update it. 将该pem文件复制到PHP可以访问的目录中,理想情况下,该文件具有644权限。您甚至可以使用444来防止篡改,并在需要更新时将其更改为644。

Then update the path in your code, for example: 然后更新代码中的路径,例如:

CURLOPT_CAINFO => '/var/www/certs/custom_name_cert.pem'

WARNING: When the website updates their SSL certificates, the above file may become out of date, and the HTTPS cURL calls may fail, breaking your application. 警告:当网站更新其SSL证书时,以上文件可能已过期,并且HTTPS cURL调用可能失败,从而破坏了您的应用程序。 Hopefully someone will answer here with a good way to automate updates to this file. 希望有人会在这里回答一个自动更新此文件的好方法。

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

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