我正在使用 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 等可以解决这个问题。
这是 Windows 中非常常见的问题。您只需将 cacert.pem
设置为 curl.cainfo
。
从 PHP 5.3.7 开始,您可以执行以下操作:
下载 https://curl.se/ca/cacert.pem 并将其保存在某处。更新 php.ini -- 添加 curl.cainfo = "PATH_TO/cacert.pem"
否则,您将需要对每个 cURL 资源执行以下操作:
curl_setopt ($ch, CURLOPT_CAINFO, "PATH_TO/cacert.pem");
curl
曾经包含接受的证书颁发机构 (CA) 的列表,但自 7.18.1 及更高版本起不再捆绑任何 CA 证书。因此,默认情况下,它会拒绝所有 TLS/SSL 证书为无法验证。
您必须获得 CA 的根证书并将 curl 指向它。 curl 的details on TLS/SSL certificates verification 中的更多详细信息。
CURLOPT_SSL_VERIFYPEER
-> false)。您要么添加您尝试使用 SSL 的站点的 CA 证书,要么禁用 CA 验证。这是仅有的两个可用选项。
CURLOPT_SSL_VERIFYPEER
设置为 false
违背了使用 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 证书是否正常####07 April 2006### 使用 Curl 打开安全 url 时可能会收到以下错误:SSL 证书问题,验证 CA 证书是否正常 I将解释错误的原因以及您应该如何处理。消除该错误的最简单方法是将以下两行添加到您的脚本中。该解决方案存在安全风险。 //警告:这将防止 curl 检测到“中间人”攻击 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 匹配的“通用名称”。这是一项健康检查,但不能保证您的程序没有被欺骗。 ###Enter the 'man in the middle'### 你的程序可能会被误导而与另一台服务器对话。这可以通过多种机制来实现,例如 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
上述解决方案很棒,但如果您使用的是 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
行添加到 both php.ini
文件。
为了爱所有圣洁的...
就我而言,我必须将 openssl.cafile
PHP 配置变量设置为 PEM 文件路径。
我相信确实有很多系统在 PHP 的配置中设置 curl.cainfo
正是需要的,但在我正在使用的环境中,即 eboraas/laravel docker 容器,它使用 Debian 8(jessie ) 和 PHP 5.6,设置该变量并没有解决问题。
我注意到 php -i
的输出没有提到任何关于该特定配置设置的内容,但它确实有几行关于 openssl
。有一个 openssl.capath
和 openssl.cafile
选项,但只需设置第二个选项,就可以通过 PHP 进行 curl 最终可以使用 HTTPS URL。
有时,如果您尝试联系的应用程序具有自签名证书,来自 http://curl.haxx.se/ca/cacert.pem 的普通 cacert.pem 并不能解决问题。
如果您确定服务端点 url,请通过浏览器点击它,以“X 509 证书链 (PEM)”格式手动保存证书。用
curl_setopt ($ch, CURLOPT_CAINFO, "pathto/{downloaded certificate chain file}");
我在亚马逊 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"
在为 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 引用。)
当我试图让 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
您基本上需要将正确的证书“签名”附加到此文件的末尾。
您可以在此处找到其中一些:如果需要,您可能需要在链中搜索/搜索其他人。
https://pki.google.com/
https://www.geotrust.com/resources/root-certificates/index.html
它们看起来像这样:
https://i.stack.imgur.com/OBrPr.png
(注意:这是一张图片,因此人们不会简单地从 stackoverflow 复制/粘贴证书)
一旦正确的证书在这个文件中,重新启动 apache 并测试。
解决方法很简单!将此行放在 curl_exec
之前:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
对我来说它有效。
2.
一起使用时,您必须将变量添加到两个单独的php.ini
文件中。请参阅stackoverflow.com/a/25706713/1101095