When using PHP with Curl is it necessary to call curl_close() after every call to curl_exec() for cookies to function properly using the CURLOPT_COOKIEJAR AND CURLOPT_COOKIEFILE options? Or can I call curl_exec() as many times as I like to different urls on the same site and still have the cookies maintained without calling curl_close() after each one? Can I use curl_exec() many times and just close it curl_close() at the end of the script?
Answers
The first you must make sure __DIR__
have write permission.
The second when you run code. You can check cookie.txt
file had been create or not.
The third you must use ONE cookie for all session. So the victim know you logged in.
And try my source
$cookies = tempnam('/tmp','cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookies);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookies);
Here is some modified code that works.
It first requests the login page to get the initial cookies and extract the required values for the login form. Next it performs a post to the login service. It then checks to see if it is trying to use javascript and meta tags to redirect to the destination URL.
It seemed like you already have code for grabbing the form fields, so I didn't post mine, but if you need it let me know. Just make sure $formFields
is an associative array with keys being the field name, and the value being the field value.
<?php
/**
* Log in to Google account and go to account page
*
*/
$USERNAME = '[email protected]';
$PASSWORD = 'password';
$COOKIEFILE = 'cookies.txt';
// initialize curl handle used for all requests
$ch = curl_init();
// set some options on the handle
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, $COOKIEFILE);
curl_setopt($ch, CURLOPT_COOKIEFILE, $COOKIEFILE);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 120);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
// url of our first request fetches the account login page
curl_setopt($ch, CURLOPT_URL,
'https://accounts.google.com/ServiceLogin?hl=en&service=alerts&continue=http://www.google.com/alerts/manage');
$data = curl_exec($ch);
// extract form fields from account login page
$formFields = getFormFields($data);
// inject email and password into form
$formFields['Email'] = $USERNAME;
$formFields['Passwd'] = $PASSWORD;
unset($formFields['PersistentCookie']);
$post_string = http_build_query($formFields); // build urlencoded POST string for login
// set url to login page as a POST request
curl_setopt($ch, CURLOPT_URL, 'https://accounts.google.com/ServiceLoginAuth');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);
// execute login request
$result = curl_exec($ch);
// check for "Redirecting" message in title to indicate success
// based on your language - you may need to change this to match some other string
if (strpos($result, '<title>Redirecting') === false) {
die("Login failed");
var_dump($result);
}
// login likely succeeded - request account page; unset POST so we do a regular GET
curl_setopt($ch, CURLOPT_URL, 'https://myaccount.google.com/?utm_source=OGB');
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_POSTFIELDS, null);
// execute request for login page using our cookies
$result = curl_exec($ch);
echo $result;
// helpef functions below
// find google "#gaia_loginform" for logging in
function getFormFields($data)
{
if (preg_match('/(<form.*?id=.?gaia_loginform.*?</form>)/is', $data, $matches)) {
$inputs = getInputs($matches[1]);
return $inputs;
} else {
die('didnt find login form');
}
}
// extract all <input fields from a form
function getInputs($form)
{
$inputs = array();
$elements = preg_match_all('/(<input[^>]+>)/is', $form, $matches);
if ($elements > 0) {
for($i = 0; $i < $elements; $i++) {
$el = preg_replace('/s{2,}/', ' ', $matches[1][$i]);
if (preg_match('/name=(?:["'])?([^"'s]*)/i', $el, $name)) {
$name = $name[1];
$value = '';
if (preg_match('/value=(?:["'])?([^"'s]*)/i', $el, $value)) {
$value = $value[1];
}
$inputs[$name] = $value;
}
}
}
return $inputs;
}
CURLOPT_POSTFIELDS
as the name suggests, is for the body (payload) of a POST
request. For GET
requests, the payload is part of the URL in the form of a query string.
In your case, you need to construct the URL with the arguments you need to send (if any), and remove the other options to cURL.
curl_setopt($ch, CURLOPT_URL, $this->service_url.'user/'.$id_user);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_HEADER, 0);
//$body = '{}';
//curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
//curl_setopt($ch, CURLOPT_POSTFIELDS,$body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
Check out the documentation for the following cURL options:
CURLOPT_COOKIE
CURLOPT_COOKIEFILE
CURLOPT_COOKIEJAR
EDIT
After reading your question more thoroughly, I'm afraid to tell you there is NO way to write the cookies to the client browser unless you redirect the client to the site you are attempting authorize them on. Browser cookies operate on a security model known as Same Origin Policy. This basically means that domains can only issue cookies for their OWN domains and may not issue cookies for others domains. In your particular case:
client --CONTACTS--> foo.com --cURL-LOGIN--> bar.com
bar.com --bar.com-COOKIE--> foo.com --foo.com-COOKIE--> client
client --foo.com-COOKIE--> bar.com (Will not work)
Basically, foo.com CAN NOT create cookies on the client for bar.com!
You should only call
curl_close()
when you know you're done with that particular handle, or if switching from its current state to a new one (ie: changing a ton of options viacurl_setopt()
would be faster by going from a clean new handle than your current "dirty" one.The cookiejar/file options are only strictly necessary for maintaining cookies between seperate curl handles/invokations. Each one's independent of the others, so the cookie files are the only way to share between them.