【问题标题】:SSL certificate problem: unable to get issuer certificateSSL 证书问题:无法获取颁发者证书
【发布时间】:2019-03-14 17:06:43
【问题描述】:

我目前正在使用证书的网站上测试 API,方法是在本地 Windows 机器上的命令行中执行使用 curl 的 php 脚本。但是脚本永远无法到达服务器。我已经为这个明显频繁的错误查找了解决方案,并尝试了以下方法,但没有成功:

  • 确保证书仍然有效。
  • 确保在 php.ini 中启用了 openssl php 扩展,并且 .dll 确实存在。
  • https://curl.haxx.se/docs/caextract.html 下载最新的证书包,如this question 的回答中所述,并将其添加到 php.ini。我还检查了我尝试联系的网站的证书颁发机构确实在该捆绑包中(在我的例子中是 Comodo)。
  • 下载了一个较旧的证书包,该包更接近网站证书有效期的开始时间。
  • 通过this link直接从证书颁发机构下载证书,并将.crt添加到我的php.ini文件中。
  • 使用this tool 将上面检索到的 .crt 文件转换为 .pem,然后将其添加到 php.ini(替换上面的那个)。

这是我用于测试的脚本(我只在命令行中使用 php 执行它):

$data = 'username=myuser&password=mypassword';
$ch = curl_init('https://my.website.com/auth');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_VERBOSE, true);
//curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_exec($ch);
curl_close($ch);

如果我取消注释其中的两行以完全绕过证书验证,它会完美运行,但我想避免这种情况。

在所有情况下,我都尝试了带有斜杠和反斜杠的路径,我确定使用了正确的 php.ini,并且 php 确实可以访问 .pem 文件位置。 php 脚本的输出证实了这一点(我已经替换了我正在使用的实际 url):

> *   Trying 192.168.200.11...
> * TCP_NODELAY set
> * Connected to my.website.com (192.168.200.11) port 443 (#0)
> * ALPN, offering http/1.1
> * successfully set certificate verify locations:   
> CAfile: C:\Development\examples\COMODORSADomainValidationSecureServerCA.pem  
> CApath: none
> * NPN, negotiated HTTP1.1
> * SSL certificate problem: unable to get issuer certificate
> * stopped the pause stream!
> * Closing connection 0

我目前不知道检查我做错了什么以及如何解决它。

【问题讨论】:

  • “无法获取颁发者证书”始终意味着您从远程端收到一个证书,在本地您无法找到对其进行签名的证书。您首先需要确切了解您获得的证书以及颁发者。然后,您需要确保在您的相关信任库中添加此颁发者证书。
  • 真正困难的部分是要知道应该如何实际检索 curl 所需的证书。我现在要感谢 Firefox 提供了执行此操作的工具。
  • 2020 年更新:firefox 不再能够提供我需要的功能,请参阅下面的答案以获得更稳定的方法。

标签: php ssl openssl php-curl


【解决方案1】:

所以,最后,这就是我最终设法做到的方式:正如错误所暗示的那样,以及几个答案还指出,我的配置中缺少证书颁发机构的证书链,并且不在包中从https://curl.haxx.se/docs/caextract.html 下载。

确实,要通过 HTTPS 成功连接到网站,除了您自己网站的证书之外,您还需要与您的证书颁发机构相关的其他证书。这可以在导出网站证书并使用用于此目的的工具对其进行可视化后在证书路径中进行检查。 Windows 有这样一个工具,默认情况下将与 .cer 文件一起使用 - 而不是文本编辑器。

通常,这些附加证书默认情况下已经存在,但就我而言,它们不是。我的认证路径如下所示:

Sectigo
   |_____Sectigo RSA Domain Validation Secure Server CA
            |_____*.example.com 

我必须为我的证书路径的 3 个部分(总共 3 个证书)中的每一个部分检索一个证书。

所以最后,我发现 this question 为我指明了正确的方向:我必须以 .cer 格式(与 PEM 相同的格式,只是另一个扩展名)导出我网站的证书,在 Windows 中打开我的证书,然后分别导出证书路径的每个部分以获得所有 3 个证书。

然后我将所有 3 个证书复制到从 https://curl.haxx.se/docs/caextract.html 下载的文件的末尾,该文件位于 C:/Development/examples/cacert.pem(您可能希望将该文件放在更靠近您的 php 的位置安装文件夹)。

然后,我将我的 php.ini 配置更改为

curl.cainfo=C:/Development/examples/cacert.pem openssl.cafile=C:/Development/examples/cacert.pem

这就成功了!我现在可以毫无问题地连接到该网站。

【讨论】:

  • 提示:导出证书时,请选择 Base-64 编码的 X.509 (.CER) 格式,否则无法复制到.pem 文件中
【解决方案2】:

你能用 curl 从命令行连接到服务器吗?

curl -vs https://my.website.com/auth --cacert C:\Development\examples\COMODORSADomainValidationSecureServerCA.pem 

可能服务器证书与您下载的捆绑包不匹配,即该证书不在捆绑包中。

如果你安装了 openssl,你可以从你的服务器中提取 CA 证书

openssl s_client -showcerts -servername server -connect server:443 > cacert.pem

类似问题的描述可以看here

【讨论】:

  • 不幸的是,我没有 linux 环境或 cygwin 来测试它,但它确实提供了一个重要线索,即错误可能是整个证书链完全或部分丢失,这确实是案例!
猜你喜欢
  • 2019-04-12
  • 2018-06-20
  • 2018-03-07
  • 1970-01-01
  • 2018-04-03
  • 2021-05-24
  • 2021-08-30
  • 2019-09-03
相关资源
最近更新 更多