php HTTPS and SSL3_GET_SERVER_CERTIFICATE:certificate verify failed, CA is OK
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6400300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HTTPS and SSL3_GET_SERVER_CERTIFICATE:certificate verify failed, CA is OK
提问by Josnidhin
I am using XAMPPfor development. Recently I upgraded my installation of xampp from an old version to 1.7.3.
我正在使用XAMPP进行开发。最近我将 xampp 的安装从旧版本升级到 1.7.3。
Now when I curl HTTPS enabled sites I get the following exception
现在,当我卷曲启用 HTTPS 的网站时,我收到以下异常
Fatal error: Uncaught exception 'RequestCore_Exception' with message 'cURL resource: Resource id #55; cURL error: SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (60)'
致命错误:未捕获异常“RequestCore_Exception”,消息为“cURL 资源:资源 ID #55;cURL 错误:SSL 证书问题,验证 CA 证书是否正常。详细信息:错误:14090086:SSL 例程:SSL3_GET_SERVER_CERTIFICATE:证书验证失败(60)'
Everyone suggest using some specific curl options from PHP code to fix this problem. I think this shouldn't be the way. Because I didn't have any problem with my old version of XAMPP and happened only after installing the new version.
每个人都建议使用 PHP 代码中的一些特定 curl 选项来解决这个问题。我认为这不应该是这种方式。因为我的旧版本XAMPP没有任何问题,只有在安装新版本后才发生。
I need help to figure out what settings change in my PHP installation, Apache etc can fix this problem.
我需要帮助弄清楚我的 PHP 安装中的哪些设置更改,Apache 等可以解决这个问题。
采纳答案by Marc B
curl used to include a list of accepted CAs, but no longer bundles ANY CA certs. So by default it'll reject all SSL certificates as unverifiable.
curl 曾经包含一个可接受的 CA 列表,但不再捆绑任何 CA 证书。因此,默认情况下它会拒绝所有 SSL 证书,因为它无法验证。
You'll have to get your CA's cert and point curl at it. More details at cURLS's Details on Server SSL Certificates.
您必须获得 CA 的证书并指向它。更多详细信息,请参见 cURLS 的服务器 SSL 证书详细信息。
回答by Артур Курицын
It's a pretty common problem in Windows. You need just to set cacert.pem
to curl.cainfo
.
这是 Windows 中非常常见的问题。您只需要设置cacert.pem
为curl.cainfo
.
Since PHP 5.3.7 you could do:
自 PHP 5.3.7 起,您可以执行以下操作:
- download https://curl.haxx.se/ca/cacert.pemand save it somewhere.
- update
php.ini
-- add curl.cainfo = "PATH_TO/cacert.pem"
- 下载https://curl.haxx.se/ca/cacert.pem并将其保存在某处。
- 更新
php.ini
-- 添加 curl.cainfo = "PATH_TO/cacert.pem"
Otherwise you will need to do the following for every cURL resource:
否则,您需要为每个 cURL 资源执行以下操作:
curl_setopt ($ch, CURLOPT_CAINFO, "PATH_TO/cacert.pem");
回答by Chris Dutrow
Warning: this can introduce security issues that SSL is designed to protect against, rendering your entire codebase insecure. It goes against every recommended practice.
警告:这可能会引入 SSL 旨在防止的安全问题,从而使您的整个代码库不安全。它违背了所有推荐的做法。
But a really simple fix that worked for me was to call:
但是对我有用的一个非常简单的修复方法是调用:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
before calling:
在打电话之前:
curl_exec():
in the php file.
在 php 文件中。
I believe that this disables all verification of SSL certificates.
我相信这会禁用对 SSL 证书的所有验证。
回答by Deepak Oberoi
Source: http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html
来源:http: //ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html
Curl: SSL certificate problem, verify that the CA cert is OK
07 April 2006
When opening a secure url with Curl you may get the following error:
SSL certificate problem, verify that the CA cert is OK
I will explain why the error and what you should do about it.
The easiest way of getting rid of the error would be adding the following two lines to your script . This solution poses a security risk tho.
//WARNING: this would prevent curl from detecting a 'man in the middle' attack curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
Let see what this two parameters do. Quoting the manual.
CURLOPT_SSL_VERIFYHOST: 1 to check the existence of a common name in the SSL peer certificate. 2 to check the existence of a common name and also verify that it matches the hostname provided.
CURLOPT_SSL_VERIFYPEER: FALSE to stop CURL from verifying the peer's certificate. Alternate certificates to verify against can be specified with the CURLOPT_CAINFO option or a certificate directory can be specified with the CURLOPT_CAPATH option. CURLOPT_SSL_VERIFYHOST may also need to be TRUE or FALSE if CURLOPT_SSL_VERIFYPEER is disabled (it defaults to 2). Setting CURLOPT_SSL_VERIFYHOST to 2 (This is the default value) will garantee that the certificate being presented to you have a 'common name' matching the URN you are using to access the remote resource. This is a healthy check but it doesn't guarantee your program is not being decieved.
Enter the 'man in the middle'
Your program could be misleaded into talking to another server instead. This can be achieved through several mechanisms, like dns or arp poisoning ( This is a story for another day). The intruder can also self-sign a certificate with the same 'comon name' your program is expecting. The communication would still be encrypted but you would be giving away your secrets to an impostor. This kind of attack is called 'man in the middle'
Defeating the 'man in the middle'
Well, we need to to verify the certificate being presented to us is good for real. We do this by comparing it against a certificate we reasonable* trust.
If the remote resource is protected by a certificate issued by one of the main CA's like Verisign, GeoTrust et al, you can safely compare against Mozilla's CA certificate bundle which you can get from http://curl.haxx.se/docs/caextract.html
Save the file
cacert.pem
somewhere in your server and set the following options in your script.curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, TRUE); curl_setopt ($ch, CURLOPT_CAINFO, "pathto/cacert.pem");
curl:SSL证书问题,验证CA证书是否OK
2006 年 4 月 7 日
使用 Curl 打开安全 url 时,您可能会收到以下错误:
SSL证书问题,验证CA证书是否OK
我将解释错误的原因以及您应该如何处理。
消除错误的最简单方法是将以下两行添加到您的脚本中。该解决方案存在安全风险。
//WARNING: this would prevent curl from detecting a 'man in the middle' attack curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
让我们看看这两个参数的作用。引用手册。
CURLOPT_SSL_VERIFYHOST: 1 检查 SSL 对等证书中是否存在通用名称。2 检查通用名称是否存在,并验证它是否与提供的主机名匹配。
CURLOPT_SSL_VERIFYPEER: FALSE 以阻止 CURL 验证对等方的证书。可以使用 CURLOPT_CAINFO 选项指定要验证的替代证书,或者可以使用 CURLOPT_CAPATH 选项指定证书目录。如果 CURLOPT_SSL_VERIFYPEER 被禁用(默认为 2),CURLOPT_SSL_VERIFYHOST 也可能需要为 TRUE 或 FALSE。将 CURLOPT_SSL_VERIFYHOST 设置为 2(这是默认值)将保证提供给您的证书具有与您用来访问远程资源的 URN 匹配的“通用名称”。这是一项健康检查,但并不能保证您的程序不会被欺骗。
输入“中间人”
您的程序可能会被误导而转而与另一台服务器交谈。这可以通过多种机制来实现,例如 dns 或 arp 中毒(这是另一天的故事)。入侵者还可以使用您的程序期望的相同“通用名称”对证书进行自签名。通信仍将被加密,但您会将您的秘密泄露给冒名顶替者。这种攻击被称为“中间人”
击败“中间人”
好吧,我们需要验证提供给我们的证书是真实的。我们通过将其与我们合理*信任的证书进行比较来做到这一点。
如果远程资源受由 Verisign、GeoTrust 等主要 CA 之一颁发的证书保护,您可以安全地与 Mozilla 的 CA 证书包进行比较,您可以从http://curl.haxx.se/docs/caextract获得 .html
将文件保存
cacert.pem
在服务器中的某个位置,并在脚本中设置以下选项。curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, TRUE); curl_setopt ($ch, CURLOPT_CAINFO, "pathto/cacert.pem");
for All above Info Credit Goes to : http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html
以上所有信息信用转到:http: //ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html
回答by Nate
The above solutions are great, but if you're using WampServer you might find setting the curl.cainfo
variable in php.ini
doesn't work.
上面的解决方案很棒,但是如果您使用的是 WampServer,您可能会发现设置curl.cainfo
变量php.ini
不起作用。
I eventually found WampServer has two php.ini
files:
我最终发现 WampServer 有两个php.ini
文件:
C:\wamp\bin\apache\Apachex.x.x\bin
C:\wamp\bin\php\phpx.x.xx
The first is apparently used for when PHP files are invoked through a web browser, while the second is used when a command is invoked through the command line or shell_exec()
.
第一个显然用于通过 Web 浏览器调用 PHP 文件时,而第二个用于通过命令行或shell_exec()
.
TL;DR
TL; 博士
If using WampServer, you must add the curl.cainfo
line to bothphp.ini
files.
如果使用 WampServer,则必须将该curl.cainfo
行添加到两个php.ini
文件中。
回答by Spencer Williams
For the love of all that is holy...
为了所有圣洁的爱...
In my case, I had to set the openssl.cafile
PHP config variable to the PEM file path.
就我而言,我必须将openssl.cafile
PHP 配置变量设置为 PEM 文件路径。
I trust it is very true that there are many systems where setting curl.cainfo
in PHP's config is exactly what is needed, but in the environment I'm working with, which is the eboraas/laraveldocker container, which uses Debian 8 (jessie) and PHP 5.6, setting that variable did not do the trick.
我相信有很多系统curl.cainfo
确实需要在 PHP 的配置中进行设置,但在我使用的环境中,这是使用 Debian 8 (jessie) 和 PHP的eboraas/laravel docker容器5.6,设置那个变量没有用。
I noticed that the output of php -i
did not mention anything about that particular config setting, but it did have a few lines about openssl
. There is both an openssl.capath
and openssl.cafile
option, but just setting the second one allowed curl via PHP to finally be okay with HTTPS URLs.
我注意到 的输出php -i
没有提到有关该特定配置设置的任何内容,但它确实有几行关于openssl
. 有一个openssl.capath
andopenssl.cafile
选项,但只需设置第二个允许 curl 通过 PHP 最终可以使用 HTTPS URL。
回答by Reinaldo Mendes
I have the same error on amazon AMI linux.
我在 amazon AMI linux 上有同样的错误。
I Solved by setting curl.cainfoon /etc/php.d/curl.ini
我通过在/etc/php.d/curl.ini上设置curl.cainfo解决了
https://gist.github.com/reinaldomendes/97fb2ce8a606ec813c4b
https://gist.github.com/reinaldomendes/97fb2ce8a606ec813c4b
Addition October 2018
2018 年 10 月
On Amazon Linux v1 edit this file
在 Amazon Linux v1 上编辑此文件
vi /etc/php.d/20-curl.ini
To add this line
添加这一行
curl.cainfo="/etc/ssl/certs/ca-bundle.crt"
回答by madRai
Sometimes if the application you try to contact has self signed certificates, the normal cacert.pem from http://curl.haxx.se/ca/cacert.pemdoes not solve the problem.
有时,如果您尝试联系的应用程序具有自签名证书,则来自http://curl.haxx.se/ca/cacert.pem的普通 cacert.pem无法解决问题。
If you are sure about the service endpoint url, hit it through browser, save the certificate manually in "X 509 certificate with chain (PEM)" format. Point this certificate file with the
如果您确定服务端点 url,请通过浏览器点击它,以“X 509 证书链 (PEM)”格式手动保存证书。将此证书文件指向
curl_setopt ($ch, CURLOPT_CAINFO, "pathto/{downloaded certificate chain file}");
回答by LOwens1931
When setting the curl options for CURLOPT_CAINFO please remember to use single quotes, using double quotes will only cause another error. So your option should look like:
为 CURLOPT_CAINFO 设置 curl 选项时请记住使用单引号,使用双引号只会导致另一个错误。所以你的选择应该是这样的:
curl_setopt ($ch, CURLOPT_CAINFO, 'c:\wamp\www\mywebfolder\cacert.pem');
Additionally, in your php.ini file setting should be written as:(notice my double quotes)
另外,在你的 php.ini 文件设置中应该写成:(注意我的双引号)
curl.cainfo = "C:\wamp\www\mywebfolder"
I put it directly below the line that says this: extension=php_curl.dll
我把它直接放在说这句话的行下面: extension=php_curl.dll
(For organizing purposes only, you could put it anywhere within your php.ini
, i just put it close to another curl reference so when I search using keyword curl I caan find both curl references in one area.)
(仅出于组织目的,您可以将它放在您的php.ini
.
回答by TrophyGeek
I ended up here when trying to get GuzzleHttp (php+apache on Mac) to get a page from www.googleapis.com.
当我试图让 GuzzleHttp(Mac 上的 php+apache)从 www.googleapis.com 获取页面时,我最终到了这里。
Here was my final solution in case it helps anyone.
这是我的最终解决方案,以防它对任何人都有帮助。
Look at the certificate chain for whatever domain is giving you this error. For me it was googleapis.com
查看出现此错误的任何域的证书链。对我来说是 googleapis.com
openssl s_client -host www.googleapis.com -port 443
You'll get back something like this:
你会得到这样的东西:
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.googleapis.com
i:/C=US/O=Google Inc/CN=Google Internet Authority G2
1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
Note: I captured this after I fixed the issue, to your chain output may look different.
注意:我在解决问题后捕获了这个,您的链输出可能看起来不同。
Then you need to look at the certificates allowed in php. Run phpinfo() in a page.
然后需要查看php中允许的证书。在页面中运行 phpinfo()。
<?php echo phpinfo();
Then look for the certificate file that's loaded from the page output:
然后查找从页面输出加载的证书文件:
openssl.cafile /usr/local/php5/ssl/certs/cacert.pem
This is the file you'll need to fix by adding the correct certificate(s) to it.
这是您需要通过向其中添加正确证书来修复的文件。
sudo nano /usr/local/php5/ssl/certs/cacert.pem
You basically need to append the correct certificate "signatures" to the end of this file.
您基本上需要将正确的证书“签名”附加到此文件的末尾。
You can find some of them here: You may need to google/search for others in the chain if you need them.
您可以在此处找到其中的一些:如果需要,您可能需要在链中搜索/搜索其他人。
They look like this:
它们看起来像这样:
(Note: This is an image so people will not simply copy/paste certificates from stackoverflow)
(注意:这是一张图片,所以人们不会简单地从 stackoverflow 复制/粘贴证书)
Once the right certificates are in this file, restart apache and test.
一旦正确的证书在此文件中,重新启动 apache 并进行测试。