首页 > 解决方案 > 修复 SSL 证书问题:无法在 PHP 中获取真实的本地颁发者证书

问题描述

在我的 PHP 代码中,有时我会对外部网站执行 cURL。今天突然出现这个错误:

SSL 证书问题:无法获取本地颁发者证书

这是我的代码的相关部分:

//downloaded from https://curl.haxx.se/docs/caextract.html
//(latest version Wed Oct 14 03:12:15 2020 GMT)    
$cacert_pem = realpath("some/path/to/cacert.pem"); 

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($query_data));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CAINFO, $cacert_pem);

在网上搜索这个问题,我从这个网站遇到了很多问题,但没有一个能真正解释发生了什么,他们只是告诉编辑 php.ini 并指向 cacert 文件,或者将文件更新为较新的版本或执行以下操作:

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

这显然是不推荐的......

然后我登陆这里https://www.offset101.com/fix-ssl-certificate-problem/解决方案之一是:

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $cacert_pem);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $cacert_pem);

错误消失了!

所以,我的问题是:

  1. 为什么会发生这种情况?我的意思是,为什么代码昨天可以工作,但今天不行。如果我理解正确,问题出在我这边,而不是在外部网站上。
  2. 描述的解决方案是否真的解决了问题,或者与将值设置为相同0?根据文档https://www.php.net/manual/es/function.curl-setopt.php,可能的值为CURLOPT_SSL_VERIFYHOST0、1 或 2。
  3. 当然......我该如何解决这个问题?

标签: phpsslcurlssl-certificateca

解决方案


为什么会发生这种情况?我的意思是,为什么代码昨天可以工作,但今天不行。如果我理解正确,问题出在我这边,而不是在外部网站上

如果没有对您的代码进行任何更改并且它突然停止工作,则问题可能出在远程站点上。一个典型的问题是站点的证书已更新,并且证书设置不正确(如缺少中间证书)或证书现在由不同的 CA 颁发。

由于看起来您的 CA 信任库只是 Firefox 也使用的常用信任库,因此我认为问题是服务器端的错误配置。由于我们不知道您尝试访问的站点,您必须自己检查。为此,您可以使用SSLLabs分析站点,然后查找任何问题,特别是“链问题”。

描述的解决方案是否真的解决了问题,还是与将值设置为 0 相同?

据我了解,这个“解决方案”是危险的错误。正如您正确意识到的那样,这些选项不将字符串作为参数,而仅将数字作为参数。给出一个字符串会将该字符串隐式转换为一个数字,除非该字符串以数字开头,否则这将导致 0。因此,在大多数情况下,您所指的帖子中显示的“修复”实际上会禁用证书验证。难怪错误随后消失了,但这当然非常危险。

当然......我该如何解决这个问题?

取决于错误的实际原因。如果服务器缺少中间证书,您可以尝试将这些缺少的证书添加到您的信任库中,即除了您已经在其中的证书之外。


推荐阅读