Joe*_*Joe 163 php rest ssl file-get-contents
我一直在尝试从我在服务器上创建的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; ?>
Run Code Online (Sandbox Code Playgroud)
该页面在第2行死亡,并出现以下错误:
- 警告:file_get_contents():SSL操作失败,代码为1. OpenSSL错误消息:错误:14090086:SSL例程:SSL3_GET_SERVER_CERTIFICATE:证书验证失败...第2行的php
- 警告:file_get_contents():无法在第2行的... php中启用加密
- 警告: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
):无法打开流:第2行的... php操作失败
我们正在使用Gentoo服务器.我们最近升级到PHP 5.6版.升级后出现此问题.
我发现,当我一个地址替换REST服务一样https://www.google.com
; 我的页面工作正常.
在我之前的一次尝试中,我将“verify_peer”=>false
其作为参数传递给file_get_contents,如下所述: file_get_contents忽略verify_peer => false? 但就像作者所指出的那样; 它没有任何区别.
我问过我们的服务器管理员是否存在php.ini文件中的这些行:
他告诉我,因为我们在Gentoo上,openssl是在我们构建时编译的; 并且它没有在php.ini文件中设置.
我也证实这allow_url_fopen
是有效的.由于这个问题的专业性; 我没有找到很多帮助信息.有没有人遇到过这样的事情?谢谢.
Joe*_*Joe 294
这是一个非常有用的链接,可以找到:
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; ?>
Run Code Online (Sandbox Code Playgroud)
eli*_*f21 145
你不应该只关闭验证.相反,你应该下载一个证书包,也许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));
Run Code Online (Sandbox Code Playgroud)
希望您尝试访问的站点的根证书位于curl包中.如果不是,则在获得站点的根证书并将其放入证书文件之前,这仍然无效.
and*_*lin 34
我通过确保在我的机器上安装了OpenSSL然后将其添加到我的php.ini来修复此问题:
openssl.cafile=/usr/local/etc/openssl/cert.pem
Run Code Online (Sandbox Code Playgroud)
Ben*_*val 15
您可以通过编写使用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;
}
Run Code Online (Sandbox Code Playgroud)
然后只需使用file_get_contents_curl
而不是file_get_contents
每当您调用以https开头的网址时.
ARU*_* NV 11
如果您的PHP版本是5,请尝试通过在终端中键入以下命令来安装cURL:
sudo apt-get install php5-curl
Run Code Online (Sandbox Code Playgroud)
<?php
$stream_context = stream_context_create([
"ssl" => [
"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);
echo $response;
?>
Run Code Online (Sandbox Code Playgroud)
刚刚测试了 PHP 7.2,运行良好。
编辑:也在 PHP 7.1 上进行了测试和工作
您基本上必须将环境变量SSL_CERT_FILE设置为从以下链接下载的ssl-certificate的PEM文件的路径:http://curl.haxx.se/ca/cacert.pem.
我花了很多时间来解决这个问题.
XAMPP 和 OSX 上的 PHP 7 也有同样的错误。
上面提到的https://stackoverflow.com/中的答案很好,但并没有完全解决我的问题。我必须提供完整的证书链才能使 file_get_contents() 再次工作。我就是这样做的:
获取根/中级证书
首先,我必须弄清楚什么是根证书和中间证书。
最方便的方法可能是像ssl-shopper这样的在线证书工具
在那里我发现了三个证书,一个服务器证书和两个链证书(一个是根证书,另一个显然是中间证书)。
我所需要做的就是在互联网上搜索他们两个。就我而言,这是根源:
thawte DV SSL SHA256 CA
它会指向他的网址thawte.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
Run Code Online (Sandbox Code Playgroud)
现在把它们全部放在一起
现在只需将它们全部合并到一个文件中即可。(也许最好将它们放入一个文件夹中,我只是将它们合并到一个文件中)。你可以这样做:
cat /tmp/thawteRoot.crt > /tmp/chain.crt
cat /tmp/thawteIntermediate.crt >> /tmp/chain.crt
cat /tmp/tmp/whatsyoururl.de.cert >> /tmp/chain.crt
Run Code Online (Sandbox Code Playgroud)
告诉 PHP 在哪里找到链
有一个方便的函数 openssl_get_cert_locations() 可以告诉您 PHP 在哪里寻找证书文件。还有这个参数,它将告诉 file_get_contents() 在哪里查找证书文件。也许两种方法都会起作用。我更喜欢参数方式。(与上面提到的解决方案相比)。
这就是我的 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));
Run Code Online (Sandbox Code Playgroud)
就这样。file_get_contents() 再次工作。没有 CURL,希望没有安全缺陷。
以下步骤将解决此问题,
curl.cainfo
并粘贴下载证书的绝对路径.curl.cainfo ="C:\wamp\htdocs\cert\cacert.pem"
希望有所帮助!!
小智 6
为我工作,我正在使用PHP 5.6。应该启用openssl扩展名,并在调用google map api verify_peer时使false以下代码对我有用。
<?php
$arrContextOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
);
$url = "https://maps.googleapis.com/maps/api/geocode/json?latlng="
. $latitude
. ","
. $longitude
. "&sensor=false&key="
. Yii::$app->params['GOOGLE_API_KEY'];
$data = file_get_contents($url, false, stream_context_create($arrContextOptions));
echo $data;
?>
Run Code Online (Sandbox Code Playgroud)
首先,您需要curl
在 PHP 中启用扩展。然后你可以使用这个函数:
function file_get_contents_ssl($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3000); // 3 sec.
curl_setopt($ch, CURLOPT_TIMEOUT, 10000); // 10 sec.
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
Run Code Online (Sandbox Code Playgroud)
它的工作原理类似于函数file_get_contents(..)。
例子:
echo file_get_contents_ssl("https://www.example.com/");
Run Code Online (Sandbox Code Playgroud)
输出:
<!doctype html>
<html>
<head>
<title>Example Domain</title>
...
Run Code Online (Sandbox Code Playgroud)
小智 5
由于我遇到了同样的问题,我只是想补充一下,在任何地方都找不到任何东西(例如,下载cacert.pem文件,在php.ini中设置cafile等)。
如果您使用的是NGINX,并且SSL证书随附“中间证书”,则需要将中间证书文件与主“ mydomain.com.crt”文件组合在一起,并且文件应该可以正常工作。Apache有一个专门针对中间证书的设置,但是NGINX没有,因此它必须与常规证书位于同一文件中。
出现此错误的原因是 PHP 没有受信任的证书颁发机构列表。
PHP 5.6及更高版本尝试自动加载系统信任的CA。与此相关的问题是可以解决的。请参阅http://php.net/manual/en/migration56.openssl.php了解更多信息。
PHP 5.5 及更早版本确实很难正确设置,因为您必须在每个请求上下文中手动指定 CA 捆绑包,这是您不想在代码中散布的事情。因此,我决定在我的代码中,对于 PHP 版本 < 5.6,SSL 验证将被禁用:
$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);
}
Run Code Online (Sandbox Code Playgroud)
在将 php 更新到 php5.6 后成为 centOS 上这个问题的受害者后,我找到了一个对我有用的解决方案。
使用此获取默认情况下要放置的证书的正确目录
php -r 'print_r(openssl_get_cert_locations()["default_cert_file"]);'
Run Code Online (Sandbox Code Playgroud)
然后使用它来获取证书并将其放在从上面的代码中找到的默认位置
wget http://curl.haxx.se/ca/cacert.pem -O <default location>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
249617 次 |
最近记录: |