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

我试图用Stripe发送一个API请求,但得到错误消息:

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

这是我正在运行的代码:

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');
}

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

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

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

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

我还尝试了这个修复:如何修复PHP CURL错误60 SSL

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

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

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

456782 次浏览
当你在使用Windows时,我认为你的路径分隔符是'\'(在Linux上是'/')。 尝试使用常量DIRECTORY_SEPARATOR。您的代码将更易于移植。< / p >

试一试:

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

EDIT:并写入完整路径。我有一些相对路径的问题(也许curl是从另一个基目录执行的?)

你试过…

curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);

如果你想冒着被中间人攻击的风险,你可以跳过验证。

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

  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;由homebrew提供)
  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所指示的位置。

我找到了一个适合我的解决办法。我把最新的版本降级到4.0,它是有效的。

在作曲家。添加“guzzlehttp/guzzle”:“~4.0”

希望它能帮助到别人

如果你在Guzzle中使用PHP 5.6, Guzzle已经切换到使用PHP库自动检测证书,而不是它的进程(裁判)。PHP概述了在这里的变化。

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

你可以使用下面的PHP命令转储PHP正在寻找的地方:

 var_dump(openssl_get_cert_locations());

获取证书包

对于OS X测试,您可以使用homebrew安装openssl brew install openssl,然后在php.ini或Zend服务器设置中使用openssl.cafile=/usr/local/etc/openssl/cert.pem(在openssl下)。

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

告诉PHP证书在哪里

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

如何解决这个问题:

  • 根据https://curl.se/docs/caextract.html的说明下载并提取cacert.pem

  • 将它保存在文件系统的某个地方(例如,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"
  • 重启您的web服务器(例如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连接到主机时,我突然出现了这个问题。当然,我可以在Guzzle/Curl中禁用验证选项,但这显然不是正确的方法。

我尝试了这里列出的一切和类似的线程,然后最终使用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,并查看您试图连接的位置的响应是否有任何变化。也许有时候这个问题并不那么“地方性”。

如果你无法更改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. cannfo。但在我的情况下,curl将尝试使用“default_cert_file”,它并不存在。

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

这是我唯一的解决办法。

请确保您直接通过窗口资源管理器打开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后,您不需要在Wamp图标中“重新启动所有服务”或关闭/重新打开CMD。

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

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

适用于php5.3+

我刚刚在使用guzzlehttp/guzzle编写器包的Laravel 4 php框架中遇到了同样的问题。由于某种原因,邮件枪的SSL证书突然停止验证,我得到了同样的“错误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文件,该文件现在可能已经过期,而不是使用旋度的环境提供的文件。修改这一行(至少在Linux上)配置Guzzle使用cURL的默认SSL验证逻辑,并解决了我的问题:

由于vendor中的文件不能被篡改,所以更好的解决方案是在使用时使用配置Guzzle客户端,但这在Laravel 4中太难做到了。

希望这为其他人节省了几个小时的调试时间……

Wamp/Wordpress/windows用户请注意。我有这个问题几个小时了,甚至没有正确的答案是为我做的,因为我编辑了错误的php.ini文件,因为这个问题是回答XAMPP而不是WAMP用户,即使这个问题是为WAMP。

以下是我所做的:

  1. 下载证书包。

  2. 把它放在C:\wamp64\bin\php\your php version\extras\ssl里面

  3. C:\wamp64\bin\apache\apache(version)\modules内部,确保文件mod_ssl.so在那里

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

  5. php.ini中启用php_openssl.dll。请注意,我的问题是,我有两个php.ini文件,我需要这样做,在他们两个。第一个可以位于WAMP任务栏图标的内部。

    enter image description here

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

    找到两个php.ini文件的位置,并找到行curl.cainfo =,并给它一个类似curl.cainfo = "C:\wamp64\bin\php\php(Version)\extras\ssl\cacert.pem"的路径

  6. 现在保存文件并重新启动服务器,您应该很好

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

它没有在链中发送任何中间确实的事情。没有错误浏览网站使用Chrome,但与PHP我得到以下错误。

卷曲度错误60

在远程web服务器配置中包含中间确实的事情后,它工作了。

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

https://whatsmychaincert.com/

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

和让php加载我的证书文件,我必须编辑php.ini在这个路径'C:\Development\bin\apache\apache2.4.33\bin\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());

然后旋度。fo应该有一个值。如果不是,那么这是不对的php.ini文件;

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

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

update-ca-certificates

如果仍然不起作用,那么您需要在证书存储中添加远程服务器的根证书和临时证书。您可以下载根证书和中间证书,并将其添加到< em > / usr /地方/分享/ ca证书< / em >目录下,然后执行命令update-ca-certificates。这应该能奏效。类似地,对于windows,您可以搜索如何添加根证书和中间证书。

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

对于WAMP,这是最终为我工作的。
虽然它与其他类似,但本页上提到的解决方案以及网络上的其他位置都不起作用。一些“minor"细节不同。
保存PEM文件的位置很重要,但没有明确地指定。
或要编辑的WHICH php.ini文件不正确。或两者兼而有之。
我正在Windows 10机器上运行WAMP 3.2.0的2020年安装

获取pem文件的链接:

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

将PEM文件保存在此位置

< p > <wamp install directory>\bin\php\php<version>\extras\ssl
eg保存的文件和路径:"T:\wamp64\bin\php\php7.3.12\extras\ssl\cacert.pem"

*(我最初将它保存在其他地方(并在php.ini文件中指示保存的位置,但这不起作用)。 可能有,也可能没有,其他位置也可以。这是推荐的位置-我不知道为什么)

< p >,
<wamp install directory> = WAMP安装的路径。
如:T:\wamp64\ < / p >

WAMP正在运行的php的<php version>:(找出,goto: WAMP icon tray -> PHP <version number>
如果显示的版本号是7.3.12,那么目录将是:php7.3.12)
如:php7.3.12 < / p >

要编辑哪个php.ini文件

要打开适当的php.ini文件进行编辑,请转到:WAMP icon tray -> PHP -> php.ini
T:\wamp64\bin\apache\apache2.4.41\bin\php.ini
注意:它不是php目录下的文件!< / p > < p > 更新:
当它看起来,就像我在编辑文件:T:\wamp64\bin\apache\apache2.4.41\bin\php.ini
它实际上是在编辑该文件的符号链接目标:T:/wamp64/bin/php/php7.3.12/phpForApache.ini.

注意,如果你遵循上面的说明,你不是直接编辑php.ini文件。你实际上是在编辑一个phpForApache.ini文件。(一个关于符号链接的信息的帖子)

如果你阅读不同WAMP目录中php.ini文件的一些顶部的注释,它特别声明不编辑该特定文件。
请确保您打开进行编辑的文件不包含此警告

安装扩展Link Shell扩展允许我通过添加的选项卡在文件属性窗口中看到符号链接的目标。这是我的一个所以回答关于这个扩展的更多信息。

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

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

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

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

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

学分:

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

我正在使用Centos 7和virtualmin的免费版本。使用Virtualmin,你可以创建一个wordpress网站。有功能,将自动更新您的ssl证书。我注意到/etc/httpd/conf/httpd.conf没有包含SSLCertificateChainFile的条目。它应该设置为/home/websitename/ssl.combined。更新相应的文件并重新启动apache为我解决了这个问题。我在尝试为wordpress安装jetpack插件时发现了我的问题。在互联网上的搜索使我意识到我没有配置SSL。我遵循Redhat的指示关于如何安装证书。我希望这对某些人有用。

狂饮版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的末尾