我在开发服务器上遇到了问题,cURL虽然可以完美地使用任何HTTP,但不能正确地使用任何HTTPS——甚至是使用不同协议的完全相同的资源(为了测试,我一直在使用HTTP和HTTPS请求google.com)。
返回的cURL错误为35:
SSL/TLS握手中出现问题。
我已经在web和SO中搜索了解决方案,所有这些都是将CURLOPT_SSL_VERIFYPEER设置为false,这不会改变任何内容,或者下载证书文件并将CURLOPT_CAINFO设置为其路径,这也不会改变任何东西。
在设置证书时,我遵循了本教程和本教程的说明,尝试下载我请求的资源的证书,并下载证书捆绑包。
我还尝试过将CURLOP_PORT显式设置为443。为了使我的问题更加彻底,我设置的其他选项是CURLOPT_VERBOSE=true、CURLOPT_RETURNTTRANSFER=true和CURLOPT_SSL_VERIFYHOST=2(我已经尝试过VERIFYPER为true和false的1和2的每种组合)。我还确保在phpinfo()
中我有OpenSSL并且它已启用。
我使用了很多在上一台生产服务器上运行良好的旧代码,所以这段代码以前也运行过。但那个主机是共享主机,我不知道那里的大部分配置。
Curl没有内置的根证书(就像大多数现代浏览器一样)。您需要明确地将其指向一个cacert.pem文件:
curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cert/file/cacert.pem');
如果没有这一点,curl就无法验证通过ssl发回的证书。每次在curl中使用SSL时,都可以使用相同的根证书文件。
您可以在此处获取cacert.pem文件:http://curl.haxx.se/docs/caextract.html
这个怎么样。它获取的可能是HTTPS谷歌主页。(由于我禁用了证书验证,我无法真正知道它是真正的谷歌主页。)它应该能帮你。
<?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
?>
查找您的操作系统是否包含证书目录。如果是这样,那么所需的CA证书通常已经包含在内。例如,在Ubuntu上,它通常是/etc/ssl/certs
。如果此目录存在,请设置CA路径参数:
curl_setopt($ch, CURLOPT_CAPATH, '/etc/ssl/certs');
或者,您可以引用单个CA证书文件。在项目中包含一个cacert.pem文件,或者将其安装在服务器上。从可信来源下载,例如cacert.org。对于单个文件,不要设置CAPATH,而只设置CAINFO:
curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem');
关闭对等和主机验证是解决真正问题的一种快速但不安全的解决方法。这些功能的存在是有充分理由的:因此,您可以通过第三方信任您所连接的系统是您所期望的系统。
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
var_dump( curl_error($ch) );
会告诉你错误。这可能是不同的原因。