无法通过HTTPS访问file_get_contents或cURL [英] Unable to file_get_contents or cURL via HTTPS

查看:193
本文介绍了无法通过HTTPS访问file_get_contents或cURL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

多年以来,我一直在使用 file_get_contents 来获取网站内容。



最近,他们更新了他们指向 HTTPS file_get_contents 的URL停止工作。



我已经阅读了先前的问题并尝试了有针对性的解决方案,但没有任何效果。



例如,我尝试了


  $ request = array(); 
$ request [] =‘主持人:example.com’;
$ request [] =‘Connection:keep-alive’;
$ request [] =‘Pragma:no-cache’;
$ request [] =‘缓存控制:无缓存’;
$ request [] =‘接受:text / html,application / xhtml + xml,application / xml; q = 0.9,image / webp,* / *; q = 0.8';
$ request [] =‘User-Agent:Mozilla / 5.0(Windows NT 5.1)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 41.0.2272.101 Safari / 537.36';
$ request [] =‘DNT:1’;
$ request [] =‘来源:https://example.com’;
$ request [] =‘引荐来源:https://example.com/entry/login’;
$ request [] =‘Accept-Encoding:gzip,deflate’;
$ request [] =‘Accept-Language:en-US,en; q = 0.8’;

初始化卷发

  $ url ='https://example.com/entry/login'; 
$ ch = curl_init($ url);

添加请求参数

  curl_setopt($ ch,CURLOPT_HTTPHEADER,$ request); 

告诉卷发以包括标题

  curl_setopt($ ch,CURLOPT_VERBOSE,true); 
curl_setopt($ ch,CURLINFO_HEADER_OUT,true);
curl_setopt($ ch,CURLOPT_HEADER,true);

返回响应

  curl_setopt($ ch,CURLOPT_RETURNTRANSFER,true); 

关注重定向
重定向可能是一个陷阱。您可能不必遵循和分析响应。

  curl_setopt($ ch,CURLOPT_FOLLOWLOCATION,true);通常,重定向是在那里设置cookie的。 
curl_setopt($ ch,CURLOPT_COOKIESESSION,true);

让卷曲手柄压缩

  curl_setopt($ ch,CURLOPT_ENCODING,); 

设置超时参数

  curl_setopt($ ch,CURLOPT_CONNECTTIMEOUT,10); 
curl_setopt($ ch,CURLOPT_TIMEOUT,10);
curl_setopt($ ch,CURLOPT_FAILONERROR,true);


发出请求并获得响应


以下内容将为您提供一切您需要了解请求。 $ info也将具有所有重定向标头。如果进行了重定向,则$ responseHeader将具有所有响应标头。


更新:新的经过全面测试的代码


这可能并不重要因为这也可以在我的机器上使用:

  echo file_get_contents($ url); 

如果curl失败,则此代码应为您提供原因,为什么会失败。


更改URL。这是一个客户端。

 < ;?php 
标头('content-type:text / plain');

$ url =‘https://amxemr.com’;
$ ch = curl_init($ url);

curl_setopt($ ch,CURLOPT_SSL_VERIFYPEER,FALSE);

curl_setopt($ ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ ch,CURLOPT_FOLLOWLOCATION,true);
curl_setopt($ ch,CURLOPT_ENCODING,);
curl_setopt($ ch,CURLOPT_CONNECTTIMEOUT,10);
curl_setopt($ ch,CURLOPT_TIMEOUT,10);
curl_setopt($ ch,CURLOPT_FAILONERROR,true);
curl_setopt($ ch,CURLOPT_ENCODING,);
curl_setopt($ ch,CURLOPT_VERBOSE,true);
curl_setopt($ ch,CURLINFO_HEADER_OUT,true);
curl_setopt($ ch,CURLOPT_HEADER,true);


$ data = curl_exec($ ch);
if(curl_errno($ ch)){
echo‘Retreive Base Page Error:’。 curl_error($ ch);
}
else {
$ info = rawurldecode(var_export(curl_getinfo($ ch),true));

//获取cookie:

$ skip = intval(curl_getinfo($ ch,CURLINFO_HEADER_SIZE));
$ responseHeader = substr($ data,0,$ skip);
$ data = substr($ data,$ skip);
echo HEADER:$ responseHeader\n;
echo \n\nINFO:$ info\n\nDATA:$ data;
}
?>

如果上述方法不起作用,请运行phpinfo()

 <?php 
phpinfo();
?>

应该有一个curl部分和openSSL。




-------------------------------------------------- ------------------


更新两次


好消息


我知道问题所在,并且能够复制您遇到的错误。

  Retreive基本页面错误:
与www.xxxx.com连接时发生未知的SSL协议错误:443

注意xxx是您提供给我的链接的站点,您可以立即删除该消息。


有趣的是,我有一台服务器没有更新。幸运的是,它具有与2008年7月相同的openSSL版本。


您需要升级openSSL。另外,file_get_contents()在此服务器上也失败。它适用于2013年2月版本的openSSL以及2014年6月。


我不能说是否需要升级其他任何东西,例如使用openSSL的功能可能(或可能不需要)进行升级。


如果格言没有破裂,我会坚持不改。我确实相信某些升级实际上是低级的。我仍在使用XP。但是它坏了,您需要修复它。


至少这不是黑暗中的一枪。我相信您必须升级。这是有条不紊的故障排除过程,能够复制您的错误。您也可以返回使用 file_get_contents()


I have been using file_get_contents to grab the contents of a site for years.

Recently, they updated their URL to HTTPS and file_get_contents stopped working.

I've read previous questions and tried marked solutions, but nothing has worked.

For example, I tried this, and it returned the following:

openssl: yes http wrapper: yes https wrapper: yes wrappers: array ( 0 => 'https', 1 => 'ftps', 2 => 'compress.zlib', 3 => 'compress.bzip2', 4 => 'php', 5 => 'file', 6 => 'data', 7 => 'http', 8 => 'ftp', 9 => 'zip', )

So then I tried this solution with file_get_contents, to no avail.

I then tried this solution with cURL to ignore encryption altogether, to no avail

No matter which solution I try, nothing is returned.

I have not added extension=php_openssl.dll and allow_url_include = On to PHP.ini as per this as this particular site is on a shared host and the hosting company does not allow the PHP.ini filed to be edited, although they may already be enabled by default.

I tried other HTTPS sites, and some work and some do not, and I'm not sure why.

I tried from a different Server (and different IP) on the same web host, and it also did not work with the target HTTPS site.

How can I debug and fix this?

UPDATE:

phpinfo shows:

curl cURL support enabled cURL Information libcurl/7.36.0 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5 libssh2/1.8.0

openssl OpenSSL support enabled OpenSSL Version OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008

解决方案

FINAL ANSWER

If your ISP will not upgrade openSSL to TLS 1.2 you should seriously consider another ISP. You should test your server with the "SSL SERVER TEST" link below. Your server likely has SSL security vulnerabilities.

The server you are trying to connect with only supports TLS 1.2 and TLS 1.1
Does not support :TLS 1.0, SSL 3, SSL2.

When an SSL request is made, as part of the SSL protocol, curl presents a list of ciphers to the host server. The server then picks which cypher protocol to use based on the list presented by curl.

The host you are trying to cont to supports these cypher suites

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)  
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)  
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x9f) 
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x9e)  
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)  
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)  
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x6b)  
TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x39) 
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027) 
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)  
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x67)  
TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x33) 
TLS_RSA_WITH_AES_256_GCM_SHA384 (0x9d) 
TLS_RSA_WITH_AES_128_GCM_SHA256 (0x9c) 
TLS_RSA_WITH_AES_256_CBC_SHA256 (0x3d) 
TLS_RSA_WITH_AES_256_CBC_SHA (0x35) 
TLS_RSA_WITH_AES_128_CBC_SHA256 (0x3c) 
TLS_RSA_WITH_AES_128_CBC_SHA (0x2f) 

Because your openSSL was released in July 2008 and TLSv1.2 was released the following month, August 2008, the best you have is TLSv1.1

POSSIBLE TEMPORARY FIX until you upgrade

I do not have a high level of confidence this will work for you

You should test your own server's SSL with something like this SSL SERVER TEST

If your server supports TLS1.1 then you can try the following. I cannot test this because I do not have the same version of curl as you on the old server with your version of openSSL.

Use the curl option, CURLOPT_SSL_CIPHER_LIST to restrain the host server from using anything other than TLS 1.1

curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'TLSv1');
curl_setopt($ch, CURL_SSLVERSION_TLSv1_1);

If not then try:

curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'DEFAULT');
curl_setopt($ch, CURL_SSLVERSION_TLSv1_1);

BOTTOM LINE

For more reasons than this issue, you need to upgrade your openSSL.

-------------------------------------------------------------------------

 
 -

PREVIOUS TROUBLESHOOTING BELOW THIS POINT

The first thing I do is turn off javascript in the Browser. If I can retrieve the page with a browser without javascript, I KNOW I can get it with PHP.

I build the request to look exactly like it does in the Browser. I go to the Network tab of the Inspector and Edit the Request Header and copy it an paste it into my code.

$request = array();
$request[] = 'Host: example.com';
$request[] = 'Connection: keep-alive';
$request[] = 'Pragma: no-cache';
$request[] = 'Cache-Control: no-cache';
$request[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
$request[] = 'User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36';
$request[] = 'DNT: 1';
$request[] = 'Origin: https://example.com';
$request[] = 'Referer: https://example.com/entry/login';
$request[] = 'Accept-Encoding: gzip, deflate';
$request[] = 'Accept-Language: en-US,en;q=0.8';

Initalize curl

$url = 'https://example.com/entry/login';
$ch = curl_init($url);

Add the request parameters

curl_setopt($ch, CURLOPT_HTTPHEADER, $request);

Tell curl to include the headers

curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_HEADER, true);

Return the response

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

Follow redirects Redirects may be a trap. You may have to NOT follow and analyze the response. Often the redirects are there to set cookies.

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_COOKIESESSION , true );

Let curl handle compression

curl_setopt($ch, CURLOPT_ENCODING,"");

Set timeout parameters

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_FAILONERROR,true);

Make the Request and get Response

The following will get everything you need to know about the requests. The $info will also have all the redirect headers too. If redirects were made the $responseHeader will have all the response headers.

UPDATE: New Fully Tested Code

This may not matter because this also works on my machine:

echo file_get_contents($url);

If curl fails, this code should give you a reason WHY it failed.

Change the url. This one belongs to a client.

<?php
header('content-type: text/plain');

$url = 'https://amxemr.com';
$ch = curl_init($url);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_ENCODING,"");
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_FAILONERROR,true);
curl_setopt($ch, CURLOPT_ENCODING,"");
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_HEADER, true);


$data = curl_exec($ch);
if (curl_errno($ch)){
    echo 'Retreive Base Page Error: ' . curl_error($ch);
}
else {
  $info = rawurldecode(var_export(curl_getinfo($ch),true));

 // Get the cookies:

  $skip = intval(curl_getinfo($ch, CURLINFO_HEADER_SIZE)); 
  $responseHeader= substr($data,0,$skip);
  $data= substr($data,$skip);
  echo "HEADER: $responseHeader\n";
  echo "\n\nINFO: $info\n\nDATA: $data";
}  
?>

If the above did not work run phpinfo()

<?php
phpinfo();
?>  

There should be a curl section and openSSL.

--------------------------------------------------------------------

UPDATE TWO

Good News

I know the problem and I was able to replicate the errors you got.

Retreive Base Page Error: 
Unknown SSL protocol error in connection to www.xxxx.com:443 

NOTE xxx was the site from the link you gave me, you can delete that message now.

Funny thing, I have one server I do not update. And by luck, it had the same version of openSSL from July 2008.

You need to upgrade your openSSL. Also the file_get_contents() failed on this server too. It worked on a Feb. 2013 version of openSSL as well as the June 2014.

I cannot say whether or not anything else needs to be upgraded like the functions that use openSSL may (or may not) need to be upgraded.

I go with the adage if it ain't broke don't fix it. I do believe some upgrades are actually down grades. I'm still on XP. But it's broke and you need to fix it.

At least it's not a shot in the dark fix. I am confident you have to upgrade. It was a methodical troubleshooting procedure that was able to duplicate your errors. You can go back to using file_get_contents() too.

这篇关于无法通过HTTPS访问file_get_contents或cURL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆