file_get_contents():代码1的SSL操作失败
我一直在尝试从我们在服务器上创build的PHP页面访问这个特定的REST服务。 我把这个问题缩小到了这两条线。 所以我的PHP页面如下所示:
<?php $response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json"); echo $response; ?>
该页面在第2行中死亡,出现以下错误:
- 警告:file_get_contents():SSL操作失败,代码为1. OpenSSL错误消息:错误:14090086:SSL例程:SSL3_GET_SERVER_CERTIFICATE:证书validation失败
- 警告:file_get_contents():无法在第2行的… php中启用encryption
- 警告:file_get_contents(
https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json
):未能打开stream:操作失败,在第2行的PHP
我们正在使用一个Gentoo服务器。 我们最近升级到PHP版本5.6。 这个问题出现后就是升级之后。
我发现当我用https://www.google.com
这样的地址replaceREST服务时, 我的网页工作得很好。
在之前的尝试中,我设置了“verify_peer”=>false
,并将其作为parameter passing给file_get_contents,如下所述: file_get_contents忽略verify_peer => false? 但是就像作者指出的那样; 它没有任何区别。
我问过我们的一个服务器pipe理员,如果我们的php.ini文件中有这些行:
- 延长= php_openssl.dll
- allow_url_fopen = On
他告诉我,既然我们使用Gentoo,openssl是在编译时编译的。 并没有在php.ini文件中设置。
我也确认allow_url_fopen
正在工作。 由于这个问题的特殊性, 我没有find大量的帮助信息。 有没有人遇到过这样的事情? 谢谢。
这是一个非常有用的链接,find:
http://php.net/manual/en/migration56.openssl.php
描述在PHP 5.6中打开ssl所做的更改的官方文档从这里我学到了另外一个我应该设置为false的参数:“verify_peer_name”=> false
所以我的工作代码如下所示:
<?php $arrContextOptions=array( "ssl"=>array( "verify_peer"=>false, "verify_peer_name"=>false, ), ); $response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json", false, stream_context_create($arrContextOptions)); echo $response; ?>
你不应该关掉validation。 相反,你应该下载一个证书包,也许curl包会做?
然后你只需要把它放在你的web服务器上,给运行php权限的用户读取文件。 那么这个代码应该为你工作:
$arrContextOptions=array( "ssl"=>array( "cafile" => "/path/to/bundle/cacert.pem", "verify_peer"=> true, "verify_peer_name"=> true, ), ); $response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json", false, stream_context_create($arrContextOptions));
希望您尝试访问的网站的根证书位于curl包中。 如果不是,直到获得站点的根证书并将其放入您的证书文件,这仍然不起作用。
我解决了这个问题,确保在我的机器上安装了OpenSSL,然后将其添加到我的php.ini中:
openssl.cafile=/usr/local/etc/openssl/cert.pem
如果你的PHP版本是5.那么试试这个修复。通过在terminal中input下面的命令来安装curl。
sudo apt-get install php5-curl
你可以通过编写一个使用curl的自定义函数来解决这个问题,如下所示:
function file_get_contents_curl( $url ) { $ch = curl_init(); curl_setopt( $ch, CURLOPT_AUTOREFERER, TRUE ); curl_setopt( $ch, CURLOPT_HEADER, 0 ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt( $ch, CURLOPT_URL, $url ); curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, TRUE ); $data = curl_exec( $ch ); curl_close( $ch ); return $data; }
然后,只要调用以https开头的url,只需使用file_get_contents_curl
而不是file_get_contents
。
您基本上必须将环境variablesSSL_CERT_FILE设置为从以下链接下载的ssl证书的PEM文件的path: http : //curl.haxx.se/ca/cacert.pem 。
我花了很多时间才弄明白这一点。
只是想添加到这个,因为我遇到了同样的问题,没有什么我可以find任何地方工作(例如下载cacert.pem文件,在php.ini中设置cafile等)
如果您使用的是NGINX,并且您的SSL证书带有“中间证书”,那么您需要将中间证书文件与您的主“mydomain.com.crt”文件结合起来使用。 Apache有一个特定于中级证书的设置,但是NGINX并不是这样,它必须与常规证书在同一个文件中。
在我的开发人员机器上使用自签名证书试图打开“ https:// localhost / …”文件时,出现了相同的ssl问题(php 7,windows上的xampp)。 显然,根证书程序集(cacert.pem)不起作用。 我只是手动复制下载的cacert.pem中的apache server.crt-File中的代码,并在php.ini中执行了openssl.cafile = path / to / cacert.pem条目
此错误的原因是PHP没有可信任的证书颁发机构的列表。
PHP 5.6和更高版本尝试自动加载系统信任的CA. 问题可以修复。 有关更多信息,请参阅http://php.net/manual/en/migration56.openssl.php 。
PHP 5.5和更早的版本确实很难正确设置,因为您必须手动在每个请求上下文中指定CA bundle,这是您不想在代码中出现的东西。 所以我决定为PHP版本<5.6的代码,SSLvalidation只是被禁用:
$req = new HTTP_Request2($url); if (version_compare(PHP_VERSION, '5.6.0', '<')) { //correct ssl validation on php 5.5 is a pain, so disable $req->setConfig('ssl_verify_host', false); $req->setConfig('ssl_verify_peer', false); }
关于类似的错误
[11-May-2017 19:19:13 America / Chicago] PHP警告:file_get_contents():SSL操作失败,代码为1. OpenSSL错误消息:错误:14090086:SSL例程:ssl3_get_server_certificate:证书validation失败
你是否检查过openssl引用的cert和目录的权限?
你可以这样做
var_dump(openssl_get_cert_locations());
为了得到类似的东西
array(8) { ["default_cert_file"]=> string(21) "/usr/lib/ssl/cert.pem" ["default_cert_file_env"]=> string(13) "SSL_CERT_FILE" ["default_cert_dir"]=> string(18) "/usr/lib/ssl/certs" ["default_cert_dir_env"]=> string(12) "SSL_CERT_DIR" ["default_private_dir"]=> string(20) "/usr/lib/ssl/private" ["default_default_cert_area"]=> string(12) "/usr/lib/ssl" ["ini_cafile"]=> string(0) "" ["ini_capath"]=> string(0) "" }
这个问题让我感到沮丧,直到我意识到我的“certs”文件夹有700个权限,而且应该有755个权限。 请记住,这不是密钥文件夹,而是证书。 我build议阅读这个链接上的SSL权限。
一旦我做到了
chmod 755 certs
问题是固定的,至less对我来说无论如何。
在XAMPP和OSX上与PHP 7有相同的错误。
在https://stackoverflow.com/上面提到的答案是好的,但它并没有完全解决我的问题。; 我必须提供完整的证书链才能使file_get_contents()再次工作。 我就这样做了:
获取根/中级证书
首先,我必须弄清楚什么是根证书和中间证书。
最方便的方式可能是像ssl-shopper这样的在线证书工具
在那里,我发现了三个证书,一个服务器证书和两个链式证书(一个是根,另一个是中间的)。
我只需要在互联网上search他们两个。 就我而言,这是根源:
解冻DV SSL SHA256 CA
这导致他的urlthawte.com 。 所以我只是把这个证书放到一个文本文件中,并为中间文件做了相同的处理。 完成。
获取主机证书
接下来我必须要下载我的服务器证书。 在Linux或OS X上,可以使用openssl完成:
openssl s_client -showcerts -connect whatsyoururl.de:443 </dev/null 2>/dev/null|openssl x509 -outform PEM > /tmp/whatsyoururl.de.cert
现在把它们放在一起
现在把所有的文件合并成一个文件。 (也许把它们放到一个文件夹中是好的,我只是将它们合并成一个文件)。 你可以这样做:
cat /tmp/thawteRoot.crt > /tmp/chain.crt cat /tmp/thawteIntermediate.crt >> /tmp/chain.crt cat /tmp/tmp/whatsyoururl.de.cert >> /tmp/chain.crt
告诉PHP哪里可以find链
有这个方便的函数openssl_get_cert_locations()告诉你,PHP正在寻找证书文件。 还有这个参数,它会告诉file_get_contents()在哪里查找证书文件。 也许这两种方式将工作。 我更喜欢参数的方式。 (与上面提到的解决scheme相比)。
所以这现在是我的PHP代码
$arrContextOptions=array( "ssl"=>array( "cafile" => "/Applications/XAMPP/xamppfiles/share/openssl/certs/chain.pem", "verify_peer"=> true, "verify_peer_name"=> true, ), ); $response = file_get_contents($myHttpsURL, 0, stream_context_create($arrContextOptions));
就这样。 file_get_contents()再次工作。 没有CURL,希望没有安全漏洞。