PHP cURL 不适用于 HTTPS

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9774349/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 07:36:41  来源:igfitidea点击:

PHP cURL Not Working with HTTPS

phpsslcurlhttps

提问by spezied

I've been having problems on my development server where cURL, while working perfectly with anything HTTP, does not function properly with anything HTTPS—even the exact same resource with different protocols (for testing I've been requesting google.com using both http and https).

我在我的开发服务器上遇到了问题,其中 cURL 在与任何 HTTP 完美配合的同时,在任何 HTTPS 上都无法正常工作——即使是使用不同协议的完全相同的资源(为了测试,我一直在请求 google.com 使用两个 http和 https)。

The cURL error returned is 35: "A problem occurred somewhere in the SSL/TLS handshake."

返回的 cURL 错误是 35:“SSL/TLS 握手中某处发生问题。”

I have combed the web and SO for solutions, and all of them have been to either set CURLOPT_SSL_VERIFYPEER to false, which changes nothing, or to download the certificate file and set CURLOPT_CAINFO to its path, which also changes nothing.

我已经梳理了网络和 SO 的解决方案,所有这些都是将 CURLOPT_SSL_VERIFYPEER 设置为 false,这没有任何改变,或者下载证书文件并将 CURLOPT_CAINFO 设置为其路径,这也没有任何改变。

When setting a certificate, I followed the instructions of this tutorialand this tutorial, trying to both download the certificate for the resource I'm requesting, and downloading a cert bundle.

设置证书时,我按照本教程本教程的说明进行操作,尝试为我请求的资源下载证书,并下载证书包。

I've also tried explicitly setting CURLOP_PORT to 443. For thoroughness of my question, other options I set are CURLOPT_VERBOSE=true, CURLOPT_RETURNTRANSFER=true, and CURLOPT_SSL_VERIFYHOST=2 (I've tried every combination of 1, and 2 with VERIFYPEER both true and false). I also have made sure in phpinfo() that I have OpenSSL and it is enabled.

我还尝试将 CURLOP_PORT 显式设置为 443。为了我的问题的彻底性,我设置的其他选项是 CURLOPT_VERBOSE=true、CURLOPT_RETURNTRANSFER=true 和 CURLOPT_SSL_VERIFYHOST=2(我已经尝试了 1 和 2 的每种组合,VERIFYPEER 都是真的和错误)。我还在 phpinfo() 中确保我有 OpenSSL 并且它已启用。

I'm using a lot of old code that worked perfectly on my last production server, so this code has worked before. But that hosting was shared hosting and I don't know most of the configuration there.

我使用了很多在我的上一个生产服务器上完美运行的旧代码,所以这段代码以前也可以使用。但是那个托管是共享托管,我不知道那里的大部分配置。

回答by Ray

Curl doesn't have built-in root certificates (like most modern browser do). You need to explicitly point it to a cacert.pem file:

Curl 没有内置的根证书(就像大多数现代浏览器一样)。您需要明确地将其指向 cacert.pem 文件:

  curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cert/file/cacert.pem');

Without this, curl cannot verify the certificate sent back via ssl. This same root certificate file can be used every time you use SSL in curl.

没有这个,curl 无法验证通过 ssl 发回的证书。每次在 curl 中使用 SSL 时,都可以使用相同的根证书文件。

You can get the cacert.pem file here: http://curl.haxx.se/docs/caextract.html

您可以在此处获取 cacert.pem 文件:http://curl.haxx.se/docs/caextract.html

回答by Joseph Lust

How about this. It fetches what might be the HTTPS Google homepage. (Since I've disabled certificate verification, I have no way to actually know that it's the real Google homepage.) It should do the trick for you.

这个怎么样。它获取可能是 HTTPS Google 主页的内容。(因为我禁用了证书验证,所以我无法真正知道它是真正的 Google 主页。)它应该可以为您解决问题。

<?PHP

// connect via SSL, but don't check cert
$handle=curl_init('https://www.google.com');
curl_setopt($handle, CURLOPT_VERBOSE, true);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
$content = curl_exec($handle);

echo $content; // show target page
?>

回答by Matt S

Find if your OS includes a directory of certificates. If so then the required CA certs will often already be included. On Ubuntu, for example, it's usually /etc/ssl/certs. If this directory exists, set the CA path parameter:

查找您的操作系统是否包含证书目录。如果是这样,那么通常已经包含所需的 CA 证书。例如,在 Ubuntu 上,它通常是/etc/ssl/certs. 如果此目录存在,请设置 CA 路径参数:

curl_setopt($ch, CURLOPT_CAPATH, '/etc/ssl/certs');

Alternatively you can reference a single CA certificate file. Include a cacert.pem file in your project or install it on your server. Download from a trusted source, e.g. cacert.org. For a single file do not set the CAPATH and instead only set CAINFO:

或者,您可以引用单个 CA 证书文件。在您的项目中包含 cacert.pem 文件或将其安装在您的服务器上。从可信来源下载,例如 cacert.org。对于单个文件,不要设置 CAPATH 而只设置 CAINFO:

curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem');

Turning off peer and host verification is a quick but insecureworkaround to the real problem. These features exist for good reason: so you can trust, via 3rd party, that the system you're connecting to is the one you expect.

关闭对等和主机验证是解决实际问题的一种快速但不安全的解决方法。这些功能的存在有充分的理由:因此您可以通过 3rd 方相信您所连接的系统是您期望的系统。

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);

回答by T.Todua

var_dump( curl_error($ch) );

will tell you the error. It might be different cause.

会告诉你错误。可能是不同的原因。