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


232

我在本地开发环境上使用WAMP,并尝试从信用卡中扣款,但收到错误消息:

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

我在Google上进行了大量搜索,很多人建议我下载此文件:cacert.pem,将其放在某个地方,然后在php.ini中引用它。这是我的php.ini中的部分:

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

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

我使用来自Apache模块的WAMP并启用了ssl_module。从PGP扩展中,我启用了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”

编辑

这是我正在运行的代码:

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',
    ]);

    dd($charge);

    // echo $charge[Input::get('stripeToken')];


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

假设您的代码没有问题,则可能是您的防火墙。尝试禁用防火墙进行测试。
Waqar ul islam 2015年

我不是在这里给你答案的吗?:)
利蒙·蒙特2015年

@limonte是可能的,必须切换项目,并且新项目可能存在相同的问题。将切换回耗时问题,也许是相同的解决方法。brb
LoveAndHappiness 2015年

1
您是否尝试过最新版本的Stripe?我看到一条提交消息,更改了与证书相关的某些信息... github.com/stripe/stripe-php/commit/…–
thelastshadow

1
@LoveAndHappiness您是否已解决此问题?我面临着与条纹相同的错误。如果您有任何解决方案,请告诉我。
2015年

Answers:


515

假设您在Windows上使用XAMPP的工作解决方案:

XAMPP服务器

  1. 其他环境类似
    • 在此处下载并提取cacert.pem(干净的文件格式/数据)

https://curl.haxx.se/docs/caextract.html

  1. 将其放在以下目录中。

C:\ xampp \ php \ extras \ ssl \ cacert.pem

  1. 在您的php.ini中,将此行放在本节中(“ c:\ xampp \ php \ php.ini”):
;;;;;;;;;;;;;;;;;;;;
; php.ini Options  ;
;;;;;;;;;;;;;;;;;;;;

curl.cainfo = "C:\xampp\php\extras\ssl\cacert.pem"
  1. 重新启动您的网络服务器/ Apache

  2. 问题解决了!

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


6
由于您的PHP版本而出现此消息。如果它比PHP 5.5高,则由于PHP 5.6的新功能而出现此错误。如果使用cURL,PHP 5.6会检查证书。
UWU_SANDUN '16

9
感谢你的回答!尽管我建议从官方curl页面使用cacert.pem:curl.haxx.se/docs/caextract.html
dieBeiden

6
只是想向无法解决此问题的任何人指出-我使用了正斜杠curl.cainfo = "C:/cacert.pem",还必须重新启动计算机才能使其正常工作。仅重新启动Web服务器是不够的。希望能
有所

1
别忘了发表评论curl.cainfo(facepalm)
Edmund Sulzanok

像魅力一样工作!谢谢
杰克

55

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

这是我所做的

下载证书捆绑包。

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

确保文件mod_ssl.so位于C:\wamp64\bin\apache\apache(version)\modules

mod_sslhttpd.confApache目录中启用C:\wamp64\bin\apache\apache2.4.27\conf

php_openssl.dll在中启用php.ini。请注意,我的问题是我有两个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"

现在保存文件并重新启动服务器,您应该一切顺利


与要使用的PHP.ini相比,您要做的两个事情都更少:如果您将apache用作SAPI客户端,则在apache目录中修改一个,和/或在客户端中修改一个。目录,如果您打算使用php.exe作为SAPI。
法比恩·哈达迪

3
关键要点是:“我两个都需要这样做”。谢谢
JaroslavKlimčík18年

1
这适用于Laravel 5.5,带有“ guzzlehttp / guzzle”:“ ^ 6.3”。Wamp服务器3.1.3。Php 7.1 *
Deepesh Thapa

这工作。谢谢
user4906240

感谢您回答
沼泽

46

如果您将PHP 5.6与Guzzle一起使用,则Guzzle已切换为使用PHP库自动检测证书,而不是其过程(ref)。PHP在这里概述了更改

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

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

 var_dump(openssl_get_cert_locations());

获取证书包

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

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

告诉PHP证书在哪里

一旦有了捆绑包,就可以将其放置在PHP已经查找的位置(在上面找到),或者openssl.cafile在php.ini中更新。(通常,/etc/php.ini/etc/php/7.0/cli/php.ini/etc/php/php.ini在Unix)。


3
是。在看到太多人提出降级多个版本号的做法显然是错误的之后,这才是正确的方法。我遵循了有关cafile的其他建议,但是没有测试为什么仍然无法加载的方法。这个openssl_get_cert_locations()函数确实可以确定我的问题。谢谢!
Web和Flow

1
感谢您提供openssl_get_cert_locations,它使调试更加容易。看起来WAMP对apache php使用的ini文件与对控制台php使用的ini文件不同。就我而言,我必须添加openssl.cafile="c:/_/cacert.pem"基于控制台的php。上一次,通过Apache使用它时,我需要curl.cainfo="c:/_/cacert.pem"使其正常工作。
psycho brm

16

Cartalyst / stripe使用的Guzzle将执行以下操作以找到适当的证书档案,以对照以下内容检查服务器证书:

  1. 检查是否 openssl.cafile在您的php.ini文件中设置了。
  2. 检查是否 curl.cainfo在您的php.ini文件中设置了。
  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指示的位置。


13

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

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

8

我所做的是var_dump(openssl_get_cert_locations()); die;在任何PHP脚本中使用的,它为我提供了有关本地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)的位置,并且能够获取它上班。

这是我唯一的解决方案。


我有类似的问题,我的位置类似于c:/usr/local/ssl/cert.pem,但是此位置不存在,请问它可能是什么,进一步,我的coluge在mac机上使用的是同一项目这就是原因,我已经尝试了其他所有方法,即在.ini文件中添加证书位置,但是它不起作用,看来您的解决方案应该可以工作,因为它有意义但不能更改该位置并且不能放置证书在不存在的位置。
AbdulMue17年

您可以尝试创建文件夹并将证书放在指定的路径吗?
George Donev

7

有一天,当Guzzle(5)脚本试图通过SSL连接到主机时,我突然出现了这个问题。当然,我可以在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等)时一切正常

这促使我联系了我一直尝试连接的域,的确,他们在THER END上遇到了一个问题,该问题已经蔓延开来。它已解决,我的脚本恢复了工作。

所以...如果您要拔头发,请给openssl试一下,看看您尝试连接的位置是否有响应。也许有时候问题并不是那么“本地化”。


6

我找到了对我有用的解决方案。我从最新版本降级为〜4.0版本,并且可以正常工作。

在composer.json中添加“ guzzlehttp / guzzle”:“〜4.0”

希望对别人有帮助


这也将阻止您使用任何5/6版功能。而是在参数数组(请求方法的第三个参数)中将verify设置为false:$ client-> request('GET','/',['verify'=> false]);
S..

3

确保您php.ini通过Window Explorer直接打开文件。(就我而言:)C:\DevPrograms\wamp64\bin\php\php5.6.25

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

然后编辑php.ini

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

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

保存后,php.ini无需在Wamp图标中“重新启动所有服务”或关闭/重新打开CMD。


2

你有没有尝试过..

curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);

如果您使用的是可信来源,则可以不必验证SSL证书。


2

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

我的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.

2

所有答案都是正确的; 但最重要的是您必须找到正确的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,然后逐个更改它们并进行检查。*


1

我刚刚在使用guzzlehttp/guzzlecomposer软件包的Laravel 4 php框架中遇到了同样的问题。由于某种原因,mailgun的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文件,该文件可能现在已过时,而不是使用cURL环境提供的文件。更改此行(至少在Linux上)会将Guzzle配置为使用cURL的默认SSL验证逻辑,并解决了我的问题:

        'verify'          => true

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

由于vendor不希望篡改其中的文件,因此更好的解决方案是按使用情况配置Guzzle客户端,但这在Laravel 4中很难做到。

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


1

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

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

cURL错误60

包括中级证书后在远程Web服务器配置中之后,它开始工作。

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

https://whatsmychaincert.com/


1

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

为了使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


0

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

update-ca-certificates

如果仍然无效,则您需要在证书存储中添加远程服务器的根证书和临时证书。您可以下载根证书和中间证书,并将它们添加到/ usr / local / share / ca-certificates目录中,然后运行command update-ca-certificates。这应该可以解决问题。同样,对于Windows,您可以搜索如何添加根证书和中间证书。

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


-1

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

尝试:

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

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


1
这不会有什么区别,因为当您使用特定的Stripe库时,实际的cURL设置已超出您的控制范围。
杰克

-1

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

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

适用于php5.3 +


是! 小心编辑apache和php版本的php.ini文件。对于WAMP用户,此答案是唯一可以解决我的问题的方法:stackoverflow.com/questions/28858351/…–
MavBzh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.