HTTPS和SSL3_GET_SERVER_CERTIFICATE:证书验证失败,CA is OK

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

现在,当我卷曲启用HTTPS的网站,我得到以下例外

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

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

我需要帮助,以确定在我的PHP安装,Apache等设置更改可以解决这个问题。

400853 次浏览

curl曾经包含一个接受的证书颁发机构(CA)列表,但自7.18.1及以后不再捆绑任何CA证书。因此默认情况下,它将拒绝所有不可验证的TLS/SSL证书。

您必须获得CA的根证书并将curl指向它。更多细节在curl的TLS/SSL证书验证的详细信息

警告:这可能会引入SSL旨在保护的安全问题,使整个代码库不安全。

但一个对我来说非常简单的解决方法是打电话:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

在调用之前:

curl_exec():

在PHP文件中。

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

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

#Curl: SSL证书问题,验证CA cert is OK# ## 2006年4月7日###

当使用Curl打开一个安全url时,您可能会得到以下错误:

SSL证书问题,请检查CA证书是否正确

我将解释为什么会出现这个错误,以及你应该怎么做。

消除错误最简单的方法是添加 下面是脚本中的两行。这个解决方案有一定的安全性 tho风险。< / p >
//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_caifo选项或证书目录指定 可以通过CURLOPT_CAPATH选项指定。 CURLOPT_SSL_VERIFYHOST也可能需要为TRUE或FALSE CURLOPT_SSL_VERIFYPEER被禁用(默认为2) CURLOPT_SSL_VERIFYHOST为2(这是默认值)将保证 提交给您的证书具有“通用名称” 匹配用于访问远程资源的URN。这是 一个健康的检查,但它不能保证您的程序不是 受骗。< / p >

###进入“中间的人”###

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

###击败“中间的人”###

好吧,我们需要验证给我们的证书是 这是真的。我们通过将其与证书进行比较来做到这一点 合理*信任。< / p >

如果远端资源受到其中一个颁发的证书的保护 主要的CA,如Verisign, GeoTrust等,你可以安全地比较 你可以从Mozilla的CA证书包中获取 http://curl.se/docs/caextract.html < / p > 保存文件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

这是Windows系统中很常见的问题。你只需要将cacert.pem设置为curl.cainfo

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

  1. 下载https://curl.se/ca/cacert.pem并保存在某个地方。
  2. 更新php.ini——添加curl。PATH_TO/cacert.pem"

否则,您需要为每个cURL资源执行以下操作:

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

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

如果确定服务端点url,通过浏览器点击,手动保存为“X 509链式证书(PEM)”格式。指向该证书文件

curl_setopt ($ch, CURLOPT_CAINFO, "pathto/{downloaded certificate chain file}");

解决方法很简单!将这一行放在curl_exec之前:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

对我来说很管用。

上面的解决方案很棒,但如果你使用WampServer,你可能会发现在php.ini中设置curl.cainfo变量不起作用。

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

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

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

博士TL;

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

在设置curlopt_caifo的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引用附近,所以当我使用关键字curl搜索时,我可以在一个区域找到两个curl引用。)

我在亚马逊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"

为了一切神圣的爱…

在我的例子中,我必须将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。

当我试图让GuzzleHttp (Mac上的php+apache)从www.googleapis.com获得一个页面时,我结束在这里。

这是我最后的解决方案,希望对大家有所帮助。

查看给您这个错误的域的证书链。对我来说是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

您基本上需要将正确的证书“签名”附加到该文件的末尾。

你可以在这里找到一些:如果你需要,你可能需要谷歌/搜索链中的其他人。

它们是这样的:

example certificate image

(注意:这是一个图像,因此人们不会简单地从stackoverflow复制/粘贴证书)

在这个文件中有了正确的证书之后,重新启动apache并进行测试。

您可以尝试重新安装ca-certificates包,或显式地允许存在问题的证书如在这里所述。