ChatGPT解决这个技术问题 Extra ChatGPT

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

我正在使用 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 等可以解决这个问题。


D
Daniel Stenberg

这是 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");

这在 OS X 上的 XAMPP 中对我有用。它解决了由于无法找到本地证书而导致 Wordpress 插件无法更新的问题。
对于其他试图在 Windows 上使用 Apache 解决此问题的人,我必须在我的 PHP 代码中设置完整路径(即 C:\PATH_TO\cacert.pem)。在 IIS 上,相对路径似乎工作正常。
如果 cacert.pem 在同一目录中,则 curl_setopt($ch, CURLOPT_CAINFO, dirname(FILE) . '/cacert.pem');将工作
将 WampServer 与 2. 一起使用时,您必须将变量添加到两个单独的 php.ini 文件中。请参阅stackoverflow.com/a/25706713/1101095
令人费解/讽刺的是,您可以通过 HTTPS 下载 curl.haxx.se/ca/cacert.pem,而无需指定任何额外选项。 curl.haxx.se 的证书是否支持 curl 本身?
D
Daniel Stenberg

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

您必须获得 CA 的根证书并将 curl 指向它。 curl 的details on TLS/SSL certificates verification 中的更多详细信息。


curl 发生在 Amazon Web 服务 php 库中。我不明白如何在不编辑库代码的情况下修复它。
然后关闭证书验证(CURLOPT_SSL_VERIFYPEER -> false)。您要么添加您尝试使用 SSL 的站点的 CA 证书,要么禁用 CA 验证。这是仅有的两个可用选项。
仅供参考 — 将 CURLOPT_SSL_VERIFYPEER 设置为 false 违背了使用 SSL 的目的。
@Till 它不会破坏 SSL 的一半目的吗?您仍然可以在您和您的同伴之间获得隐私:您只是没有您的同伴的真实性。
没有真实性,加密您发送的数据有什么意义?如果您已被 MITMed,那么无论如何数据都会受到损害
m
miken32

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

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

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

打电话之前:

curl_exec():

在 php 文件中。

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


...并且通过禁用证书验证,您为潜在的 MITM 攻击敞开了大门,而 SSL/TLS 原本旨在防止这种攻击。不要这样做!
是的。我应该在答案中引起更多关注。仅当您没有处理任何重要的事情时才这样做。我在 localhost 上使用它来访问我个人编程的网站。
对我投反对票。这是使您的代码正常工作的肮脏修复,但不是解决方案。 Артур Курицын 提供的答案要好得多。
@Bruno 这是一个完美的解决方案,对于帮助脚本、测试、受信任的应用程序、Intranet,......每个对 SSL 有一点了解的人都知道在哪些情况下可以跳过证书验证。所以所有关于这个答案的“聪明”评论和“不要这样做”之类的东西都是胡说八道!
...“每个对 SSL 略知一二的人 [...]”...您会惊讶地发现有多少人甚至不知道一点关于 SSL/TLS 的基础知识,而只是来了在这里复制/粘贴他们的错误消息的快速修复。
D
Daniel Stenberg

来源: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


通常认为有礼貌地注明您的信息来源并仅引用与问题相关的某些部分,而不是简单地复制并粘贴在此处!
对不起,我已经离开了,是的,我为此感谢丹并更新了帖子
至少迪帕克努力研究它。 @danherd 所以,danherd,您刚刚进行了研究,发现他从某个地方获取了代码?这段代码的归属权是什么?与其浪费时间去寻找别人的错误,不如试着自己帮助别人。不争,分享!
N
Nate

上述解决方案很棒,但如果您使用的是 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 文件。


S
Spencer Williams

为了爱所有圣洁的...

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

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

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


谢谢!设置 curl.cainfo 对我也不起作用,但设置 openssl.cafile 可以!我在带有 XAMPP 和 PHP 7.1.1 的 Windows 7 上。
@knezmilos 你是如何设置 openssl.cafile 的?你在哪里下载的,如何激活它?
好吧,已经有一段时间了,但我认为它是这样的: curl.cainfo = "C:\xampp\cacert\cacert.pem" 和 openssl.cafile= "C:\xampp\cacert\cacert.pem" 在 php 中。 ini,虽然我想我是从这里的一个答案中得到 pem 文件的。
“为了所有圣洁的爱……”确实如此。这适用于我的 Ubuntu 18.08/Apache/Php7.2 设置。如果 curl 错误指向正确的文件,那么它肯定是 openssls 错误
m
madRai

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

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

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

T
Tim

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

很好,谢谢!我更新了问题以准确添加我所做的为我解决问题的方法,而不是创建另一个答案。
L
Leistungsabfall

在为 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 引用。)


我希望 php.ini 应该指向 pem 文件而不是它的父文件夹
T
TrophyGeek

当我试图让 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 并测试。


s
site

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


P
Perry

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

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

对我来说它有效。


永远不要禁用对等验证,除非您不在乎数据在传输过程中是否受到损害。
同意。如果您想要一个安全的应用程序,您需要对等验证。
“永远不要禁用对等验证”,除非您想要默认浏览器功能哈哈。另外,为什么这个投票如此低?这是唯一简短、甜蜜、中肯且有效的答案。
@AdamF 仅供参考,浏览器默认会验证对等证书,它们只为您提供手动绕过错误的选项,并发出警告。