PHP CURL & HTTPS
PhpCurlHttpsPhp Problem Overview
I found this function that does an AWESOME job (IMHO): http://nadeausoftware.com/articles/2007/06/php_tip_how_get_web_page_using_curl
/**
* Get a web file (HTML, XHTML, XML, image, etc.) from a URL. Return an
* array containing the HTTP server response header fields and content.
*/
function get_web_page( $url )
{
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => false, // don't return headers
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_ENCODING => "", // handle all encodings
CURLOPT_USERAGENT => "spider", // who am i
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
CURLOPT_TIMEOUT => 120, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
);
$ch = curl_init( $url );
curl_setopt_array( $ch, $options );
$content = curl_exec( $ch );
$err = curl_errno( $ch );
$errmsg = curl_error( $ch );
$header = curl_getinfo( $ch );
curl_close( $ch );
$header['errno'] = $err;
$header['errmsg'] = $errmsg;
$header['content'] = $content;
return $header;
}
The only problem I have is that it doesn't work for https://. Anny ideas what I need to do to make this work for https? Thanks!
Php Solutions
Solution 1 - Php
Quick fix, add this in your options:
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false)
Now you have no idea what host you're actually connecting to, because cURL will not verify the certificate in any way. Hope you enjoy man-in-the-middle attacks!
Or just add it to your current function:
/**
* Get a web file (HTML, XHTML, XML, image, etc.) from a URL. Return an
* array containing the HTTP server response header fields and content.
*/
function get_web_page( $url )
{
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => false, // don't return headers
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_ENCODING => "", // handle all encodings
CURLOPT_USERAGENT => "spider", // who am i
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
CURLOPT_TIMEOUT => 120, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
CURLOPT_SSL_VERIFYPEER => false // Disabled SSL Cert checks
);
$ch = curl_init( $url );
curl_setopt_array( $ch, $options );
$content = curl_exec( $ch );
$err = curl_errno( $ch );
$errmsg = curl_error( $ch );
$header = curl_getinfo( $ch );
curl_close( $ch );
$header['errno'] = $err;
$header['errmsg'] = $errmsg;
$header['content'] = $content;
return $header;
}
Solution 2 - Php
I was trying to use CURL to do some https API calls with php and ran into this problem. I noticed a recommendation on the php site which got me up and running: http://php.net/manual/en/function.curl-setopt.php#110457
> Please everyone, stop setting CURLOPT_SSL_VERIFYPEER to false or 0. If > your PHP installation doesn't have an up-to-date CA root certificate > bundle, download the one at the curl website and save it on your > server: > > http://curl.haxx.se/docs/caextract.html > > Then set a path to it in your php.ini file, e.g. on Windows: > > curl.cainfo=c:\php\cacert.pem > > Turning off CURLOPT_SSL_VERIFYPEER allows man in the middle (MITM) > attacks, which you don't want!
Solution 3 - Php
Another option like Gavin Palmer answer is to use the .pem
file but with a curl option
-
download the last updated
.pem
file from https://curl.haxx.se/docs/caextract.html and save it somewhere on your server(outside the public folder) -
set the option in your code instead of the
php.ini
file.
In your code
curl_setopt($ch, CURLOPT_CAINFO, $_SERVER['DOCUMENT_ROOT'] . "/../cacert-2017-09-20.pem");
NOTE: setting the cainfo in the php.ini
like @Gavin Palmer did is better than setting it in your code like I did, because it will save a disk IO every time the function is called, I just make it like this in case you want to test the cainfo file on the fly instead of changing the php.ini
while testing your function.
Solution 4 - Php
One important note, the solution mentioned above will not work on local host, you have to upload your code to server and then it will work. I was getting no error, than bad request, the problem was I was using localhost (test.dev,myproject.git). Both solution above work, the solution that uses SSL cert is recommended.
-
Go to https://curl.haxx.se/docs/caextract.html, download the latest cacert.pem. Store is somewhere (not in public folder - but will work regardless)
-
Use this code
>
> $user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0)
> AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132
> Safari/537.36"; $ch = curl_init(); curl_setopt($ch,
> CURLOPT_POST,1);
>
> curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch,
> CURLOPT_USERAGENT, $user_agent); curl_setopt($ch,
> CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
> true); curl_setopt($ch, CURLOPT_CAINFO, $_SERVER['DOCUMENT_ROOT'] .
> "/ssl/cacert.pem");
>
> $result=curl_exec ($ch); curl_close ($ch);
>
> echo "Results:
".$result;
>
> //echo "
Path:".$_SERVER['DOCUMENT_ROOT'] . "/ssl/cacert.pem";
> // this is for troubleshooting only ?>
- Upload the code to live server and test.