208

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

现在,当我 curl 启用 HTTPS 的站点时,出现以下异常

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

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

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

4

12 回答 12

292

这是 Windows 中非常常见的问题。您只需设置cacert.pemcurl.cainfo.

从 PHP 5.3.7 开始,您可以执行以下操作:

  1. 下载https://curl.se/ca/cacert.pem并将其保存在某处。
  2. 更新php.ini-- 添加 curl.cainfo = "PATH_TO/cacert.pem"

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

curl_setopt ($ch, CURLOPT_CAINFO, "PATH_TO/cacert.pem");
于 2013-05-11T07:54:51.177 回答
145

curl用于包含接受的证书颁发机构 (CA) 的列表,但不再捆绑自 7.18.1 及更高版本以来的任何 CA 证书。因此,默认情况下,它会拒绝所有 TLS/SSL 证书为无法验证。

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

于 2011-06-19T05:23:16.410 回答
85

警告:这可能会引入 SSL 旨在防止的安全问题,从而使您的整个代码库不安全。它违背了所有推荐的做法。

但是对我有用的一个非常简单的解决方法是调用:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

打电话之前:

curl_exec():

在 php 文件中。

我相信这会禁用 SSL 证书的所有验证。

于 2012-05-12T19:59:16.787 回答
55

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

#Curl:SSL证书问题,验证CA证书是否OK####07 April 2006###

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

SSL证书问题,验证CA证书是否OK

我将解释错误的原因以及您应该怎么做。

消除该错误的最简单方法是将以下两行添加到您的脚本中。该解决方案存在安全风险。

//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_VERIFYPEER 被禁用(默认为 2),CURLOPT_SSL_VERIFYHOST 也可能需要为 TRUE 或 FALSE。将 CURLOPT_SSL_VERIFYHOST 设置为 2(这是默认值)将保证提供给您的证书具有与您用于访问远程资源的 URN 匹配的“通用名称”。这是一项健康检查,但不能保证您的程序没有被欺骗。

###输入'中间人'###

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

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

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

如果远程资源受到 Verisign、GeoTrust 等主要 CA 颁发的证书的保护,您可以安全地与 Mozilla 的 CA 证书包进行比较,您可以从 http://curl.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

于 2012-09-06T06:07:52.850 回答
17

上述解决方案很棒,但如果您使用的是 WampServer,您可能会发现设置curl.cainfo变量 inphp.ini不起作用。

我最终发现 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文件中。

于 2014-09-07T03:04:34.390 回答
6

为了爱所有圣洁的...

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

我相信确实有很多系统curl.cainfo在 PHP 的配置中进行设置正是需要的,但是在我正在使用的环境中,它是使用 Debian 8 (jessie) 和 PHP的eboraas/laravel docker容器5.6,设置该变量并没有成功。

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

于 2017-02-28T04:42:26.653 回答
4

有时,如果您尝试联系的应用程序具有自签名证书,来自http://curl.haxx.se/ca/cacert.pem的普通 cacert.pem并不能解决问题。

如果您确定服务端点 url,请通过浏览器点击它,以“X 509 证书链 (PEM)”格式手动保存证书。用

curl_setopt ($ch, CURLOPT_CAINFO, "pathto/{downloaded certificate chain file}");   
于 2013-12-18T18:52:16.887 回答
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"
于 2014-10-09T02:43:16.277 回答
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 引用附近,因此当我使用关键字 curl 搜索时,我可以在一个区域找到两个 curl 引用。)

于 2014-09-30T15:27:31.840 回答
2

当我试图让 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.ini 中允许的证书。在页面中运行 phpinfo()。

<?php echo phpinfo();

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

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

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

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

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

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

它们看起来像这样:

示例证书图像

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

一旦正确的证书在这个文件中,重新启动 apache 并测试。

于 2017-04-18T21:45:23.330 回答
0

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

于 2019-04-11T18:34:07.967 回答
-5

解决方法很简单!将此行放在前面curl_exec

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

对我来说它有效。

于 2014-01-02T18:32:37.343 回答