cURL 错误 60:SSL 证书:无法获取本地颁发者证书

cURL error 60: SSL certificate: unable to get local issuer certificate

我正在尝试使用 Stripe 发送 API 请求,但收到错误消息:

cURL error 60: SSL certificate problem: unable to get local issuer certificate

这是我的代码 运行:

public function chargeStripe()
{
    $stripe = new Stripe;
    $stripe = Stripe::make(env('STRIPE_PUBLIC_KEY'));

    $charge = $stripe->charges()->create([
        'amount'   => 2900,
        'customer' => Input::get('stripeEmail'),
        'currency' => 'EUR',
    ]);

    return Redirect::route('step1');
}

我在 Google 上搜索了很多,很多人建议我下载这个文件:cacert.pem,把它放在某个地方并在我的 php.ini 中引用它。这是我的部分 php.ini:

curl.cainfo = "C:\Windows\cacert.pem"

然而,即使在多次重启我的服务器并更改路径后,我仍然收到相同的错误消息。

我在 Apache 中启用了 ssl_module,并且在我的 php.ini 中启用了 php_curl。

我也试过这个修复:How to fix PHP CURL Error 60 SSL

这表明我将这些行添加到我的 cURL 选项中:

curl_setopt($process, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
curl_setopt($process, CURLOPT_SSL_VERIFYPEER, true);

在哪里可以为我的 cURL 添加选项?显然不是通过命令行,因为我的 CLI 找不到命令“curl_setopt”

当您使用 Windows 时,我认为您的路径分隔符是“\”(和 Linux 上的“/”)。 尝试使用常量 DIRECTORY_SEPARATOR。您的代码将更具可移植性。

尝试:

curl_setopt($process, CURLOPT_CAINFO, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'cacert.pem');

编辑:并写下完整路径。我在相对路径方面遇到了一些问题(也许 curl 是从另一个基本目录执行的?)

你试过了吗..

curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);

如果您使用的是可信来源,则可以跳过验证。

Guzzle,由 cartalyst/stripe 使用,将执行以下操作以找到合适的证书存档来检查服务器证书:

  1. 检查您的 php.ini 文件中是否设置了 openssl.cafile
  2. 检查您的 php.ini 文件中是否设置了 curl.cainfo
  3. 检查/etc/pki/tls/certs/ca-bundle.crt是否存在(Red Hat、CentOS、Fedora;由ca-certificates包提供)
  4. 检查 /etc/ssl/certs/ca-certificates.crt 是否存在(Ubuntu,Debian;由 ca-certificates 包提供)
  5. 检查 /usr/local/share/certs/ca-root-nss.crt 是否存在(FreeBSD;由 ca_root_nss 软件包提供)
  6. 检查是否 /usr/local/etc/openssl/cert.pem(OS X;由自制程序提供)
  7. 检查C:\windows\system32\curl-ca-bundle.crt是否存在(Windows)
  8. 检查 C:\windows\curl-ca-bundle.crt 是否存在 (Windows)

您需要通过简单的测试来确保前两个设置的值已正确定义:

echo "openssl.cafile: ", ini_get('openssl.cafile'), "\n";
echo "curl.cainfo: ", ini_get('curl.cainfo'), "\n";

或者,尝试将文件写入#7 或#8 指示的位置。

我找到了适合我的解决方案。我从最新的 guzzle 降级到版本 ~4.0 并且它有效。

在 composer.json 添加 "guzzlehttp/guzzle": "~4.0"

希望对大家有所帮助

如果您将 PHP 5.6 与 Guzzle 一起使用,Guzzle 已切换到使用 PHP 库自动检测证书而不是它的进程(ref). PHP outlines the changes here

找出 PHP/Guzzle 在哪里寻找证书

您可以使用以下 PHP 命令转储 PHP 正在查找的位置:

 var_dump(openssl_get_cert_locations());

获取证书包

对于 OS X 测试,您可以使用自制软件安装 openssl brew install openssl,然后在 php.ini 或 Zend Server 设置(在 OpenSSL 下)中使用 openssl.cafile=/usr/local/etc/openssl/cert.pem

也可从 curl 网站 curl/Mozilla 获得证书包:https://curl.haxx.se/docs/caextract.html

告诉PHP证书在哪里

一旦你有了一个包,要么把它放在 PHP 已经在寻找的地方(你在上面找到的),要么在 php.ini 中更新 openssl.cafile。 (通常,在 Unix 上 /etc/php.ini/etc/php/7.0/cli/php.ini/etc/php/php.ini。)

如何解决这个问题:

  • 下载解压cacert.pem following the instructions at https://curl.se/docs/caextract.html

  • 将其保存在文件系统中的某处(例如,XAMPP 用户可能会使用 C:\xampp\php\extras\ssl\cacert.pem

  • 在你的php.ini中,把这个文件位置放在[curl]部分(放在[openssl]部分也是个好主意):

[curl]
curl.cainfo = "C:\xampp\php\extras\ssl\cacert.pem"

[openssl]
openssl.cafile = "C:\xampp\php\extras\ssl\cacert.pem"
  • 重新启动您的网络服务器(例如 Apache)和 PHP FPM 服务器(如果适用)

(参考:https://laracasts.com/discuss/channels/general-discussion/curl-error-60-ssl-certificate-problem-unable-to-get-local-issuer-certificate

有一天,当 Guzzle(5) 脚本试图通过 SSL 连接到主机时,我遇到了这个问题 out-of-the-blue。当然,我可以在 Guzzle/Curl 中禁用 VERIFY 选项,但这显然不是正确的方法。

我尝试了此处和类似主题中列出的所有内容,然后最终使用 openssl 进入终端以针对我尝试连接的域进行测试:

openssl s_client -connect example.com:443 

... 并收到前几行指示:

CONNECTED(00000003)
depth=0 CN = example.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = example.com
verify error:num=21:unable to verify the first certificate
verify return:1 

...虽然在尝试其他目的地时一切正常(即:google.com,等等)

这促使我联系了我一直试图连接的域,事实上,他们在他们的一端遇到了一个悄悄出现的问题。它已解决,我的脚本恢复工作。

所以...如果您不放心,请试一试 openssl,看看您尝试连接的位置的响应是否有任何问题。也许问题并非如此 'local' 毕竟有时候。

如果您无法更改 php.ini,您也可以通过如下代码指向 cacert.pem 文件:

$http = new GuzzleHttp\Client(['verify' => '/path/to/cacert.pem']);
$client = new Google_Client();
$client->setHttpClient($http);

我所做的是在任何 php 脚本中使用 var_dump(openssl_get_cert_locations()); die;,这为我提供了有关本地 php 使用的默认值的信息:

array (size=8)
  'default_cert_file' => string 'c:/openssl-1.0.1c/ssl/cert.pem' (length=30)
  'default_cert_file_env' => string 'SSL_CERT_FILE' (length=13)
  'default_cert_dir' => string 'c:/openssl-1.0.1c/ssl/certs' (length=27)
  'default_cert_dir_env' => string 'SSL_CERT_DIR' (length=12)
  'default_private_dir' => string 'c:/openssl-1.0.1c/ssl/private' (length=29)
  'default_default_cert_area' => string 'c:/openssl-1.0.1c/ssl' (length=21)
  'ini_cafile' => string 'E:\xampp\php\extras\ssl\cacert.pem' (length=34)
  'ini_capath' => string '' (length=0)

如您所见,我设置了 ini_cafile 或 ini 选项 curl.cainfo。但就我而言,curl 会尝试使用不存在的 "default_cert_file"。

我将文件从 https://curl.haxx.se/ca/cacert.pem 复制到 "default_cert_file" 的位置 (c:/openssl-1.0.1c/ssl/cert.pem) 并且我能够将它获取到工作。

这是我唯一的解决方案。

请确保您直接通过 Window 资源管理器打开 php.ini 文件。 (在我的例子中:C:\DevPrograms\wamp64\bin\php\php5.6.25)。

不要使用系统托盘 Wamp/Xamp 图标菜单中 php.ini 的快捷方式。此快捷方式在这种情况下不起作用。

然后编辑 php.ini :

curl.cainfo ="C:/DevPrograms/wamp64/bin/php/cacert.pem" 

openssl.cafile="C:/DevPrograms/wamp64/bin/php/cacert.pem"

保存 php.ini 后,您不需要 "Restart All Services" 在 Wamp 图标或 close/re-open CMD 中。

如果您使用 WAMP,您还应该在 php.ini 中为 Apache 添加证书行(除了默认的 php.ini 文件):

[curl]
curl.cainfo = C:\your_location\cacert.pem

适用于 php5.3+

我刚刚在使用 guzzlehttp/guzzle composer 包的 Laravel 4 php 框架中遇到了同样的问题。出于某种原因,mailgun 的 SSL 证书突然停止验证,我收到了同样的 "error 60" 消息。

如果您像我一样在无法访问 php.ini 的共享主机上,则其他解决方案不可行。在任何情况下,Guzzle 都有这个客户端初始化代码,很可能会使 php.ini 效果无效:

// vendor/guzzlehttp/guzzle/src/Client.php
    $settings = [
        'allow_redirects' => true,
        'exceptions'      => true,
        'decode_content'  => true,
        'verify'          => __DIR__ . '/cacert.pem'
    ];

这里 Guzzle 强制使用它自己的内部 cacert.pem 文件,而不是使用 cURL's environment 提供的文件,该文件现在可能已经过时了。更改此行(至少在 Linux 上)将 Guzzle 配置为使用 cURL 的默认 SSL 验证逻辑并解决了我的问题:

        'verify'          => true

如果您不关心 SSL 连接的安全性,也可以将此设置为 false,但这不是一个好的解决方案。

由于 vendor 中的文件不会被篡改,更好的解决方案是 configure the Guzzle client 使用,但这在 Laravel 4 中很难做到.

希望这可以为其他人节省几个小时的调试时间...

注意 Wamp/Wordpress/windows 用户。我遇到这个问题好几个小时了,甚至连正确的答案都没有为我解决,因为我编辑了错误的 php.ini 文件,因为问题是针对 XAMPP 而不是针对 WAMP 用户的,即使问题是针对 WAMP 的。

这是我所做的

下载 certificate bundle.

放在C:\wamp64\bin\php\your php version\extras\ssl

里面

确保文件 mod_ssl.soC:\wamp64\bin\apache\apache(version)\modules

在 Apache 目录 httpd.conf 中启用 mod_ssl C:\wamp64\bin\apache\apache2.4.27\conf

php.ini 中启用 php_openssl.dll。请注意,我的问题是我有两个 php.ini 文件,我需要在这两个文件中执行此操作。第一个位于您的 WAMP 任务栏图标内。

另一个位于C:\wamp64\bin\php\php(Version)

找到两个 php.ini 文件的位置并找到行 curl.cainfo = 并给它一个像这样的路径

curl.cainfo = "C:\wamp64\bin\php\php(Version)\extras\ssl\cacert.pem"

现在保存文件并重新启动服务器,您应该可以开始了

这可能是一个边缘案例,但在我的情况下,问题不是 客户端 conf(我已经有 curl.cainfophp.ini 中配置),而是远程服务器未正确配置:

它没有在链中发送任何中间 certs。使用 Chrome 浏览网站没有错误,但使用 PHP 时出现以下错误。

cURL error 60

在远程 Web 服务器配置中包含 中级证书 后,它起作用了。

您可以使用此站点检查服务器的 SSL 配置:

https://whatsmychaincert.com/

当我运行'var_dump(php_ini_loaded_file());' 我在我的页面上得到这个输出 'C:\Development\bin\apache\apache2.4.33\bin\php.ini' (length=50)'

并让 php 加载我的证书文件,我必须在此路径 'C:\Development\bin\apache\apache2.4.33\bin\php.ini' 中编辑 php.ini 并在我下载的位置添加 openssl.cafile="C:/Development/bin/php/php7.2.4/extras/ssl/cacert.pem" 并从 https://curl.haxx.se/docs/caextract.html

放置我的证书文件

我在 windows 10,使用 drupal 8、wamp 和 php7.2.4

我花了太多时间来解决这个问题。

我有 PHP 版本 5.5,我需要升级到 5.6。

在版本 < 5.6 中,Guzzle 将使用它自己的 cacert.pem 文件,但在更高版本的 PHP 中,它将使用系统的 cacert.pem 文件。

我也从这里 https://curl.haxx.se/docs/caextract.html 下载文件并将其设置在 php.ini。

在 Guzzles StreamHandler.php 文件 https://github.com/guzzle/guzzle/blob/0773d442aa96baf19d7195f14ba6e9c2da11f8ed/src/Handler/StreamHandler.php#L437

中找到答案
        // PHP 5.6 or greater will find the system cert by default. When
        // < 5.6, use the Guzzle bundled cacert.

所有答案都正确; 但最重要的是 是您必须找到正确的php.ini 文件。 在 cmd “php --ini”中检查此命令不是正确的答案 以找到正确的 php.ini 文件。

如果您编辑

curl.cainfo ="PATH/cacert.pem"

并检查

var_dump(openssl_get_cert_locations()); 

那么 curl.cainfo 应该有一个值。 如果不是那就不对php.ini文件;

*我建议您在wamp/bin或xxamp/bin或您使用的任何服务器中搜索*.ini并逐一更改并检查。 *

这个问题我有一个妥善的解决方案,让我们尝试了解这个问题的根本原因。当无法使用系统证书存储中的根证书验证远程服务器 ssl 或远程 ssl 未与链证书一起安装时,会出现此问题。如果您有一个具有 root ssh 访问权限的 linux 系统,那么在这种情况下,您可以尝试使用以下命令更新您的证书存储:

update-ca-certificates

如果还是不行,那么您需要在您的证书库中添加远程服务器的根证书和临时证书。您可以下载根证书和中间证书并将它们添加到 /usr/local/share/ca-certificates 目录中,然后 运行 命令 update-ca-certificates。这应该可以解决问题。同样,对于 windows,您可以搜索如何添加根证书和中间证书。

解决此问题的另一种方法是要求远程服务器团队将 ssl 证书添加为域根证书、中间证书和根证书的捆绑包。

对于 WAMP,这就是最终对我有用的方法。
虽然它与其他类似,但此页面和网络上其他位置提到的解决方案均无效。一些“次要”细节有所不同。
保存 PEM 文件的位置很重要,但指定得不够清楚。
或者要编辑的 php.ini 个文件不正确。或两者兼而有之。
我正在 运行 在 Windows 10 机器上安装 2020 版 WAMP 3.2.0。

Link获取pem文件:

http://curl.haxx.se/ca/cacert.pem
复制整个页面并将其另存为:cacert.pem,在下面提到的位置。

在此位置保存 PEM 文件

<wamp install directory>\bin\php\php<version>\extras\ssl
例如保存的文件和路径:“T:\wamp64\bin\php\php7.3.12\extras\ssl\cacert.pem”

*(我本来是保存在别处的(并在php.ini文件中标明了保存位置,但是没用)。 可能有也可能没有,其他位置也可以。这是推荐的位置 - 我不知道为什么。)

哪里
<wamp install directory> = WAMP 安装路径。
例如:T:\wamp64\

php 的

<php version> WAMP 是 运行ning:(要找出答案,请转到:WAMP icon tray -> PHP <version number>
如果显示的版本号是 7.3.12,那么目录将是:php7.3.12)
例如:php7.3.12

要编辑哪个 php.ini 文件

要打开正确的 php.ini 文件进行编辑,请转到:WAMP icon tray -> PHP -> php.ini
例如:T:\wamp64\bin\apache\apache2.4.41\bin\php.ini
注意:它不是 php 目录中的文件!

更新:
虽然它 看起来 就像我正在编辑文件:T:\wamp64\bin\apache\apache2.4.41\bin\php.ini,
它实际上是在编辑该文件的 symlink 目标:T:/wamp64/bin/php/php7.3.12/phpForApache.ini.

请注意,如果您按照上述说明操作,您并不是在直接编辑 php.ini 文件。您实际上是在编辑 phpForApache.ini 文件。 (一个 post 包含关于 symlinks 的信息)

如果您阅读了各种 WAMP 目录中 一些 文件顶部的评论,它明确指出不要编辑该特定文件。
确保您打开进行编辑的文件不包含此警告。

正在安装我的 Link Shell Extension allowed me to see the target of the symlink in the file Properites window, via an added tab. here is an SO answer 扩展程序以及有关此扩展程序的更多信息。

如果您 运行 不同版本的 php 在不同的时间,您可能需要将 PEM 文件保存在每个相关的 php 目录中。

要在 php.ini 文件中进行的编辑:

将 PEM 文件的路径粘贴到以下位置。

  • 取消注释 ;curl.cainfo = 并粘贴到您的 PEM 文件的路径。
    例如:curl.cainfo = "T:\wamp64\bin\php\php7.3.12\extras\ssl\cacert.pem"

  • 取消注释 ;openssl.cafile= 并粘贴到您的 PEM 文件的路径。
    例如:openssl.cafile="T:\wamp64\bin\php\php7.3.12\extras\ssl\cacert.pem"

学分:

虽然不是官方资源,但这里有一个 link 回到 YouTube 视频,它为我理清了最后的细节:https://www.youtube.com/watch?v=Fn1V4yQNgLs.

我使用的是带有免费版 virtualmin 的 Centos 7。使用 Virtualmin,您可以创建一个 wordpress 网站。有一种功能会自动为您更新您的 ssl 证书。我注意到 /etc/httpd/conf/httpd.conf 不包含 SSLCertificateChainFile 的条目。应将其设置为 /home/websitename/ssl.combined 之类的内容。相应地更新该文件并重新启动 apache 为我解决了这个问题。我在尝试为 wordpress 安装 jetpack 插件时发现了我的问题。在互联网上搜索让我意识到 I didn't have SSL Configured. I followed Redhat's instructions 关于如何安装证书。我希望这对某人有用。

Guzzle 版本 5

这个默认配置很适合我。它将禁用所需的 https。

  $options = [
    'defaults' => ['verify' => false],
  ];
  new GuzzleClient($options);

其他情况下,要设置ca的路径,改为:

['verify' => '/path/to/cacert.pem']

对于那些试图在本地计算机上使用 Wordpress 的应用程序密码功能的人。您需要更新 wp-includes\certificates\ca-bundle.crt

在文本编辑器中打开此文件并附加您的服务器证书。

  1. 打开您的自签名证书 (.crt) 文件并

  2. 复制

    之间的所有内容(包括

----开始证书-----

-----证书结束-----

  1. 粘贴在wp-includes\certificates\ca-bundle.crt
  2. 的末尾