How to get file_get_contents() to work with HTTPS?
Try the following script to see if there is an https wrapper available for your php scripts.
$w = stream_get_wrappers();
echo 'openssl: ', extension_loaded ('openssl') ? 'yes':'no', "\n";
echo 'http wrapper: ', in_array('http', $w) ? 'yes':'no', "\n";
echo 'https wrapper: ', in_array('https', $w) ? 'yes':'no', "\n";
echo 'wrappers: ', var_export($w);
the output should be something like
openssl: yes
http wrapper: yes
https wrapper: yes
wrappers: array(11) {
[...]
}
file_get_content not working for https in php
According to php.net
When using SSL, Microsoft IIS will violate the protocol by closing the
connection without sending a close_notify indicator. PHP will report
this as "SSL: Fatal Protocol Error" when you reach the end of the
data. To work around this, the value of error_reporting should be
lowered to a level that does not include warnings. PHP can detect
buggy IIS server software when you open the stream using the https://
wrapper and will suppress the warning. When using fsockopen() to
create an ssl:// socket, the developer is responsible for detecting
and suppressing this warning.
Source link
Unable to file_get_contents or cURL via HTTPS
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.
file_get_contents from remote client and SSL
It sounds like the certificate verification is failing because it doesn't have a reference file of root certificates to check it with. See this Stack Overflow answer.
file_get_contents(): SSL operation failed with code 1, Failed to enable crypto
This was an enormously helpful link to find:
http://php.net/manual/en/migration56.openssl.php
An official document describing the changes made to open ssl in PHP 5.6
From here I learned of one more parameter I should have set to false: "verify_peer_name"=>false
Note: This has very significant security implications. Disabling verification potentially permits a MITM attacker to use an invalid certificate to eavesdrop on the requests. While it may be useful to do this in local development, other approaches should be used in production.
So my working code looks like this:
<?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; ?>
Using file_get_contents with basic auth and SSL
Curiosity is a good thing so it's cool to dig this problem without falling back to cURL before fixing this problem.
<?php
$username = "XXXXXXXXXX";
$password = "XXXXXXXXXX";
$url = "https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api";
$context = stream_context_create(array(
"http" => array(
"header" => "Authorization: Basic " . base64_encode("$username:$password"),
"protocol_version" => 1.1, //IMPORTANT IS HERE
)));
$data = file_get_contents($url, false, $context);
echo $data;
The fact is the server does not support HTTP/1.0. So you haven't any problem with SSL/TLS nor with your user agent. It is just the server that support HTTP from 1.1.
As said in the stream_context_create documentation the default protocol_version used in stream_context_create is 1.0. That's why you got an error 500.
Related Topics
Simplest PHP Example For Retrieving User_Timeline With Twitter API Version 1.1
Multiple Inputs With Same Name Through Post in PHP
Create Subdomains on the Fly With .Htaccess (PHP)
Is There a Code Obfuscator For PHP
Creating the Singleton Design Pattern in PHP5
Recursive Function to Generate Multidimensional Array from Database Result
Invoking a PHP Script from a MySQL Trigger
Displaying HTML With Blade Shows the HTML Code
When Should I Use MySQLi Instead of MySQL
MySQLi Update Throwing Call to a Member Function Bind_Param() Error
How to Create a Pdo Parameterized Query With a Like Statement
How to Group Subarrays by a Column Value
Form Submit With Ajax Passing Form Data to PHP Without Page Refresh