php 无法使用 cURL 连接到 HTTPS 站点。而是返回 0 长度的内容。我能做什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/316099/
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
Can't connect to HTTPS site using cURL. Returns 0 length content instead. What can I do?
提问by alex
I have a site that connects using cURL (latest version) to a secure gateway for payment.
我有一个使用 cURL(最新版本)连接到安全网关进行支付的站点。
The problem is cURL always returns 0 length content. I get headers only. And only when I set cURL to return headers. I have the following flags in place.
问题是 cURL 总是返回 0 长度的内容。我只得到标题。并且仅当我设置 cURL 以返回标头时。我有以下标志。
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_URL, $gatewayURI);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_POST, 1);
The header returned is
返回的标题是
HTTP/1.1 100 Continue
HTTP/1.1 200 OK
Date: Tue, 25 Nov 2008 01:08:34 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Content-Length: 0
Content-Type: text/html
Set-Cookie: ASPSESSIONIDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; path=/
Cache-control: private
I have also tried cURL'ing different sites and they return content fine. I think the problem might have something to do with the https connection.
我也试过 cURL'ing 不同的网站,他们返回的内容很好。我认为问题可能与 https 连接有关。
I have spoken with the company and they are unhelpful.
我已经和公司谈过了,他们没有帮助。
Has anyone else experienced this error and know a work around? Should I ditch cURL and try and use fsockopen()?
有没有其他人遇到过这个错误并知道解决方法?我应该放弃 cURL 并尝试使用fsockopen()吗?
Thank you. :)
谢谢你。:)
采纳答案by too much php
You should also try checking the error messages in curl_error(). You might need to do this once after each curl_* function.
您还应该尝试检查 curl_error() 中的错误消息。您可能需要在每个 curl_* 函数之后执行一次此操作。
回答by SchizoDuckie
I had the same problem today. Curl comes with an outdated file to authenticate HTTPS certificates from.
我今天遇到了同样的问题。Curl 带有一个过时的文件来验证 HTTPS 证书。
get the new one from:
从以下位置获取新的:
http://curl.haxx.se/ca/cacert.pem
http://curl.haxx.se/ca/cacert.pem
save it into some dir on your site
将其保存到您网站上的某个目录中
and add
并添加
curl_setopt ($curl_ch, CURLOPT_CAINFO, dirname(__FILE__)."/cacert.pem");
To every request :-)
对于每个请求:-)
IGNORE any dumbass comments about disabling CURLOPT_VERIFYPEER and CURLOPT_VERIFYHOST!! That leaves your code vulnerable to man in the middle attacks!
忽略任何关于禁用 CURLOPT_VERIFYPEER 和 CURLOPT_VERIFYHOST 的愚蠢评论!!这会使您的代码容易受到中间人攻击!
December 2016 edit:
2016 年 12 月编辑:
Solve this properly by using Jasen's method mentioned below.
使用下面提到的 Jasen 方法正确解决这个问题。
add curl.cainfo=/etc/ssl/certs/ca-certificates.crtto you php.ini
添加curl.cainfo=/etc/ssl/certs/ca-certificates.crt到你的 php.ini
October 2017 edit:
2017 年 10 月编辑:
There is now a composer package that helps you manage the ca certificates, so that you're not vulnerable if your cacert.pem becomes outdated due to revoking certificates.
现在有一个 composer 包可以帮助您管理 ca 证书,这样如果您的 cacert.pem 由于撤销证书而过时,您就不会受到攻击。
https://github.com/paragonie/certainty-> composer require paragonie/certainty:dev-master
https://github.com/paragonie/certainty->composer require paragonie/certainty:dev-master
回答by mixdev
Note: This is strictly not production use. If you want to quickly debug, this may be useful. Otherwise, please use @SchizoDuckie's answer above.
注意:这绝对不是生产用途。如果您想快速调试,这可能很有用。否则,请使用上面@SchizoDuckie 的回答。
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
Just add them. It works.
只需添加它们。有用。
回答by Cobra_Fast
Just had a very similar problem and solved it by adding
刚刚遇到了一个非常相似的问题,并通过添加解决了它
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
Apparently the site I'm fetching redirects to another location and php-curl doesn't follow redirects by default.
显然,我正在获取的站点重定向到另一个位置,而 php-curl 默认不遵循重定向。
回答by user203319
I had a situation where this helped: (PHP 5.4.16 on Windows)
我遇到了这样的情况:(Windows 上的 PHP 5.4.16)
curl_setopt($ch, CURLOPT_SSLVERSION, 3);
回答by Issac Kelly
Whenever I'm testing something with PHP/Curl, I try it from the command line first, figure out what works, and then port my options to PHP.
每当我用 PHP/Curl 测试某些东西时,我首先从命令行尝试它,找出有效的方法,然后将我的选项移植到 PHP。
回答by Elzo Valugi
Sometimes you have to upgrade your Curl certificates to latest version not to have errors with https.
有时您必须将 Curl 证书升级到最新版本,以免 https 出错。
回答by Elzo Valugi
I used file_get_contentsusing stream_create_contextand it works fine:
我file_get_contents使用过stream_create_context,效果很好:
$postdataStr = http_build_query($postdataArr);
$context_options = array (
'http' => array ( <blink> // this will allways be http!!!</blink>
'method' => 'POST',
'header'=> "Content-type: application/x-www-form-urlencoded\r\n"
. "Content-Length: " . strlen($postdataArr) . "\r\n"
. "Cookie: " . $cookies."\r\n"
'content' => $postdataStr
)
);
$context = stream_context_create($context_options);
$HTTPSReq = file_get_contents('https://www.example.com/', false, $context);
回答by Elzo Valugi
I discovered this error on a recent application project. I was writing to run from the command line or the browser window, so I was using server detection to get the relative URL of the document I was asking for. The trouble was, the site is https, and each time I attempted to access http://(sameserver), cURL helpfully changed it to https.
我在最近的一个应用程序项目中发现了这个错误。我写的是从命令行或浏览器窗口运行,所以我使用服务器检测来获取我要求的文档的相对 URL。问题是,该站点是 https,每次我尝试访问http://(同一服务器)时,cURL 都会帮助将其更改为 https。
This works fine from the browser, but from the command-line, I'd then get an SSL error even with both verify's set to false. What I had to do was,
这在浏览器中工作正常,但是从命令行中,即使两个验证都设置为 false,我也会收到 SSL 错误。我必须做的是,
1) Check $_SERVER['HTTP_HOST']. If present, use ($_SERVER['HTTPS'] ? "https://" : "http://").$_SERVER['HTTP_HOST']
1) 检查 $_SERVER['HTTP_HOST']。如果存在,请使用 ($_SERVER['HTTPS'] ? "https://" : "http://").$_SERVER['HTTP_HOST']
2) Check $_SERVER['COMPUTERNAME'], and if it matched the production server, provide the https URL. ("https://(servername)")
2) 检查$_SERVER['COMPUTERNAME'],如果匹配生产服务器,提供https URL。(" https://(服务器名)")
3) If neither condition passed, it means I'm running command-line on a different server, and use "http://localhost".
3) 如果两个条件都不通过,则意味着我在不同的服务器上运行命令行,并使用“ http://localhost”。
Now, this worked, but it's a hack. Also, I never did figure out why on one server (https) cURL changed my URL, while on the other (also https) it left my URL alone.
现在,这有效,但它是一个黑客。此外,我从来没有弄清楚为什么在一个服务器 (https) 上 cURL 更改了我的 URL,而在另一台服务器 (也是 https) 上它留下了我的 URL。
Weird.
奇怪的。
回答by Elzo Valugi
there might be a problem at your web hosting company from where you are testing the secure communication for gateway, that they might not allow you to do that.
您正在测试网关安全通信的网络托管公司可能存在问题,他们可能不允许您这样做。
also there might be a username, password that must be provided before connecting to remote host.
在连接到远程主机之前,可能还必须提供用户名和密码。
or your IP might need to be in the list of approved IP for the remote server for communication to initiate.
或者您的 IP 可能需要在远程服务器的批准 IP 列表中才能启动通信。

