HTTPS和SSL3_GET_SERVER_CERTIFICATE:证书验证失败,CA正常

时间:2011-06-19 03:18:21

标签: php ssl curl openssl ca

我正在使用XAMPP进行开发。最近我将xampp的安装从旧版本升级到1.7.3。

现在,当我卷曲启用HTTPS的网站时,我收到以下异常

  

致命错误:带有消息的未捕获异常“RequestCore_Exception”   'cURL资源:资源       id#55; cURL错误:SSL证书问题,验证CA证书是否正常。细节:       错误:14090086:SSL例程:SSL3_GET_SERVER_CERTIFICATE:证书验证失败(60)'

每个人都建议使用PHP代码中的一些特定curl选项来解决此问题。我认为这不应该是这样的。因为我的旧版XAMPP没有任何问题,只是在安装新版本后才发生。

我需要帮助来确定我的PHP安装中哪些设置发生了变化,Apache等可以解决这个问题。

12 个答案:

答案 0 :(得分:285)

这是Windows中一个非常常见的问题。您只需将cacert.pem设置为curl.cainfo

从PHP 5.3.7开始,你可以这样做:

  1. 下载https://curl.haxx.se/ca/cacert.pem并将其保存在某处。
  2. 更新php.ini - 添加curl.cainfo =“PATH_TO / cacert.pem”
  3. 否则,您需要为每个cURL资源执行以下操作:

    curl_setopt ($ch, CURLOPT_CAINFO, "PATH_TO/cacert.pem");
    

答案 1 :(得分:143)

curl用于包含已接受的CA列表,但不再捆绑任何CA证书。因此,默认情况下,它会拒绝所有SSL证书作为无法验证的。

您必须获得CA的证书并指出它的卷曲。更多细节见cURLS的Details on Server SSL Certificates

答案 2 :(得分:83)

警告:这可能会引入SSL旨在防范的安全问题,从而导致整个代码库不安全。这违背了所有建议的做法。

但对我有用的一个非常简单的解决方法就是打电话:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

致电之前:

curl_exec():

在php文件中。

我认为这会禁用SSL证书的所有验证。

答案 3 :(得分:50)

来源:http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html

  

卷曲:SSL证书问题,验证CA证书是否正常

     

2006年4月7日

     

使用Curl打开安全网址时,您可能会收到以下错误:

     

SSL证书问题,验证CA证书是否正常

     

我将解释为什么错误以及你应该怎么做。

     

摆脱错误的最简单方法是添加   以下两行到您的脚本。该解决方案具有安全性   冒险。

//WARNING: this would prevent curl from detecting a 'man in the middle' attack
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0); 
     

让我们看看这两个参数是做什么的。引用手册。

     

CURLOPT_SSL_VERIFYHOST :1检查SSL对等证书中是否存在公用名。 2检查是否存在通用名称   并验证它是否与提供的主机名匹配。

     

CURLOPT_SSL_VERIFYPEER :FALSE停止CURL验证对等方的证书。要验证的备用证书可以是   使用CURLOPT_CAINFO选项或证书目录指定   可以使用CURLOPT_CAPATH选项指定。   如果,CURLOPT_SSL_VERIFYHOST也可能需要为TRUE或FALSE   CURLOPT_SSL_VERIFYPEER已禁用(默认为2)。设置   CURLOPT_SSL_VERIFYHOST到2(这是默认值)将保证   提交给您的证书具有“通用名称”   匹配您用于访问远程资源的URN。这是   一个健康的检查,但它不保证你的程序不存在   受骗。

     

输入'中间人'

     

您的程序可能会被误导与另一台服务器通信   代替。这可以通过几种机制来实现,比如dns或   arp中毒(这是另一天的故事)。入侵者可以   还可以使用与您的程序相同的“comon name”自签一份证书   期待。通信仍然会加密,但你会   将你的秘密泄露给冒名顶替者。这种攻击是   被称为“中间人”

     

击败'中间人'

     

好吧,我们需要验证提交给我们的证书是否正确   真实的。我们通过将它与我们的证书进行比较来实现   合理的*信任。

     

如果远程资源受到其中一个颁发的证书的保护   主要的CA就像Verisign,GeoTrust等,你可以安全地进行比较   针对Mozilla的CA证书包,您可以从中获取   http://curl.haxx.se/docs/caextract.html

     

将文件cacert.pem保存在服务器中的某个位置并设置   以下脚本中的选项。

curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, TRUE); 
curl_setopt ($ch, CURLOPT_CAINFO, "pathto/cacert.pem");

以上所有信息转到:http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html

答案 4 :(得分:16)

上述解决方案非常棒,但如果您使用WampServer,您可能会发现在curl.cainfo中设置php.ini变量无法正常工作。

我最终发现WampServer有两个php.ini个文件:

C:\wamp\bin\apache\Apachex.x.x\bin
C:\wamp\bin\php\phpx.x.xx

第一个显然用于通过Web浏览器调用PHP文件,而第二个用于通过命令行或shell_exec()调用命令时。

<强> TL; DR

如果使用WampServer,您必须将curl.cainfo行添加到 php.ini个文件中。

答案 5 :(得分:4)

有时,如果您尝试联系的应用程序具有自签名证书,则http://curl.haxx.se/ca/cacert.pem中的正常cacert.pem无法解决问题。

如果您确定服务端点网址,请通过浏览器点击它,手动将证书保存在“带链(PEM)的X 509证书”格式中。使用

指向此证书文件
curl_setopt ($ch, CURLOPT_CAINFO, "pathto/{downloaded certificate chain file}");   

答案 6 :(得分:4)

我在亚马逊AMI linux上遇到同样的错误。

我通过在 /etc/php.d/curl.ini

上设置 curl.cainfo 来解决

https://gist.github.com/reinaldomendes/97fb2ce8a606ec813c4b

加入2018年10月

在Amazon Linux v1上编辑此文件

vi /etc/php.d/20-curl.ini

添加此行

curl.cainfo="/etc/ssl/certs/ca-bundle.crt"

答案 7 :(得分:4)

为了所有神圣的爱...

就我而言,我必须将openssl.cafile PHP配置变量设置为PEM文件路径。

我相信很多系统都在PHP的配置中设置curl.cainfo正是我们需要的,但在我正在使用的环境中,这是eboraas/laravel docker容器,它使用Debian 8(jessie)和PHP 5.6,设置该变量不起作用。

我注意到php -i的输出没有提到有关该特定配置设置的任何内容,但确实有一些关于openssl的内容。有一个openssl.capathopenssl.cafile选项,但只需设置第二个允许curl通过PHP最终可以使用HTTPS URL。

答案 8 :(得分:3)

设置CURLOPT_CAINFO的curl选项时请记住使用单引号,使用双引号只会导致另一个错误。所以你的选择应该是这样的:

curl_setopt ($ch, CURLOPT_CAINFO, 'c:\wamp\www\mywebfolder\cacert.pem');

此外,在你的php.ini文件中,设置应该写成:(注意我的双引号)

curl.cainfo = "C:\wamp\www\mywebfolder"

我将它直接放在说明这一行的行下方:extension=php_curl.dll

(仅限于组织目的,您可以将它放在php.ini内的任何位置,我只需将其放在另一个卷曲引用附近,这样当我使用关键字curl搜索时,我可以在一个区域中找到两个卷曲引用。)< / p>

答案 9 :(得分:1)

当我试图从www.googleapis.com获取GuzzleHttp(Mac +上的php + apache)时,我最终到了这里。

这是我的最终解决方案,以防万一。

查看证书链中的任何域名都会给您带来此错误。对我来说这是googleapis.com

openssl s_client -host www.googleapis.com -port 443

你会得到这样的东西:

Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.googleapis.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority

注意:我在修复问题后捕获了这个,你的链输出可能看起来不一样。

然后你需要查看php中允许的证书。在页面中运行phpinfo()。

<?php echo phpinfo();

然后查找从页面输出中加载的证书文件:

openssl.cafile  /usr/local/php5/ssl/certs/cacert.pem

这是您需要通过向其添加正确的证书来修复的文件。

sudo nano /usr/local/php5/ssl/certs/cacert.pem

您基本上需要附加正确的证书&#34;签名&#34;到这个文件的末尾。

您可以在此处找到其中一些内容:如果您需要,可能需要谷歌/搜索链中的其他人。

他们看起来像这样:

example certificate image

注意:这是一张图片,所以人们不会简单地从stackoverflow复制/粘贴证书

在此文件中包含正确的证书后,重新启动apache并进行测试。

答案 10 :(得分:0)

您可以尝试重新安装ca-certificates软件包,或按照here所述明确允许有问题的证书。

答案 11 :(得分:-3)

解决方案非常简单!将此行放在curl_exec之前:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

对我而言,它有效。