Make session work with Curl (ZF2) - php

I'm working with REST in my Zend Framework 2 application. In order to test my rest calls, I use Curl to send REST requests as follows:
$client = new Http\Client();
$client->setAdapter(new Http\Client\Adapter\Curl());
$request = new Http\Request();
$request->setUri($url);
$request->setMethod($method);
$response = $client->dispatch($request);
$jsonString = $response->getContent();
Everthing works fine except that the Curl requests seem to ignore the session. I need access to the logged-in user in my rest request handling to e.g. make Acl work. When I send REST request using AngularJS, the session actually works. Here's how I set up the session:
$storage = new SessionArrayStorage();
$manager = new SessionManager($config, $storage);
$session = new Session('surveylab', $manager);
How can I pass the session information to Curl, so I get access to the session in the Curl requests?

Checkout the cURL options for:
CURLOPT_COOKIEFILE
CURLOPT_COOKIEJAR
look for examples for the cURL usage of them:
curl_setopt($ch, CURLOPT_COOKIEFILE, "/tmp/cookie.txt");
curl_setopt($ch, CURLOPT_COOKIEJAR, "/tmp/cookie.txt");

Send your login credentials as post to your login url, extract the cookies from the result and send them with the next request. I don't know if your application updates the cookies over time but you should update them if necessary.
Some example code:
curl_setopt_array($ch, array(
CURLOPT_URL => "http://your/url",
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_HTTPHEADER => array('Cookie: ' . $cookies . '"'),
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_POST => count($postData),
CURLOPT_POSTFIELDS => $post_string
));

Related

Sending Cookie via cURL (CURLOPT_COOKIEFILE) not working - Salesforce streaming API

I am having trouble trying to send a Cookie via cURL. The specific case scenario is related to Salesforce streaming API but I think it applies to similar PHP situations.
This is the issue, there are 2 requests done, the first one receives a cookie named BAYEUX_BROWSER and uses CURLOPT_COOKIEJAR to store the cookie in the server; the second request uses the stored cookie to set a session.
This is the snippet of the first request:
$cookie_filename = '/some/patch/cookies.txt';
$ch = curl_init();
// cURL cookie options being set
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, $filename);
After the request is made, the file cookies.txt is created successfully, it also contains the BAYEUX_BROWSER cookie inside, here is an example of the returned cookies:
# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
xxx.my.salesforce.com FALSE /cometd/ TRUE 0 BAYEUX_BROWSER e38bvb418bj8bztzkeaan2wx18y3
#HttpOnly_xxx.my.salesforce.com FALSE /cometd/ FALSE 0 t !0vaFlJER5UsrfIGrfKp9YI2pARkJi5YS8O/yCf8GE+6HiX+CvWWacnC3MzF+OXsuC3USJWIP3jamDQ==
.salesforce.com TRUE / FALSE 1629832267 BrowserId kGpyG-Y9EeqF7jOgs3LDaA
xxx.my.salesforce.com FALSE / FALSE 1598388400 sfdc-stream !jH2NPGTjjg64odBoo4aJz7403s94D3xXnkFrzyha9kaRQGVKxQfnpfplyv8vwVzqy4p9godcH/z7O1A=
The second request uses CURLOPT_COOKIEFILE to set the location of the cookies file and make the request using them:
$cookie_filename = '/some/patch/cookies.txt';
$ch = curl_init();
// cURL cookie options being set
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIEFILE, $filename);
The issue here is that the response from Salesforce is that the BAYEUX_BROWSER cookie is not present in the request, here is the exact response:
400::Client xxxx has established a session, but no BAYEUX_BROWSER cookie present
I have been trying for hours now to change and play with different cURL options to see if I can enable the cookie but had no luck.
I am not sure if I need to change the COOKIE format, or if I am missing something, I honestly don't know at this point.
Any one had a similar issue or knows what is wrong with my code?
Got this issue solved using the Guzzle package (https://github.com/guzzle/guzzle) instead of cURL.
$cookie_filename = '/some/patch/cookies.json';
$jar = new \GuzzleHttp\Cookie\FileCookieJar( $filename, true );
$client = new \GuzzleHttp\Client();
// First response
$response = $client->request( 'POST', $url1, [
'headers' => [...],
'cookies' => $jar,
'form_params' => ['message' => json_encode( $message )],
] );
if ( $response->getStatusCode() === 200 ) {
$response = json_decode( (string)$response->getBody() );
// Set client ID
$response = $client->request( 'POST', $url2, [
'headers' => [...],
'cookies' => $jar,
'form_params' => ['message' => json_encode( $message )],
] );
}

PHP Curl Authentication Issue using API

I am trying to get data from a REST api that uses a token for authentication in the URL. I can pass the relevant parameters in a web browser and get the data with no problem, however as soon as I try to do it in a PHP script with curl, I get a 401 error saying http authentication is required.
Have tried many different options but cannot get it to work, any help would be appreciated. My code is below, have removed site id and changed api_key
API documentation says:
The API can be accessed via HTTPS protocol only. SolarEdge monitoring server supports both HTTPS/1.0 and HTTPS/1.1 protocols.
All APIs are secured via an access token:
Every access to the API requires a valid token as a URL parameter named api_key.
For example: api_key= L4QLVQ1LOKCQX2193VSEICXW61NP6B1O
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_SSL_VERIFYHOST => 0,
CURLINFO_HEADER_OUT => 1,
CURLOPT_POST => 1,
CURLOPT_HTTPAUTH, CURLAUTH_ANY,
CURLOPT_URL => 'https://monitoringapi.solaredge.com/site/?????/energyDetails',
CURLOPT_USERPWD, 'api_key:6X0kjehfdgksdljsgksdjhfksdhfglksd',
CURLOPT_HTTPHEADER=>array(
"timeUnit:DAY",
"meters=PRODUCTION,CONSUMPTION",
"startTime:2017-12-09 00:00:00",
"endTime:2017-12-09 23:59:59"),
));
$resp = curl_exec($curl);
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// Close request to clear up some resources
curl_close($curl);
echo $resp;
echo "<br>$status_code";
//var_dump ($resp);
//print_r ($resp);
?>
Check the documentation again. Search for (Basic) Authentication.
You should look for something like this:
Authorization: <type> <credentials>
e.g. Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
The HTTP 401 Unauthorized client error status response code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource.
This status is sent with a WWW-Authenticate header that contains information on how to authorize correctly.
This status is similar to 403, but in this case, authentication is possible.
Try your code again like this (add your API key) and report back the results:
$curl = curl_init();
curl_setopt_array($curl, array(
// CURLOPT_PORT=> 443,
// CURLOPT_RETURNTRANSFER => 1,
// CURLOPT_SSL_VERIFYPEER => 0,
// CURLOPT_SSL_VERIFYHOST => 0,
CURLINFO_HEADER_OUT => 1,
CURLOPT_POST => 1,
CURLOPT_HTTPAUTH, CURLAUTH_ANY,
CURLOPT_URL => 'https://monitoringapi.solaredge.com/site/?????/energyDetails',
CURLOPT_USERPWD, 'api_key:6X0kjehfdgksdljsgksdjhfksdhfglksd',
CURLOPT_HTTPHEADER=>array(
"timeUnit:DAY",
"meters=PRODUCTION,CONSUMPTION",
"startTime:2017-12-09 00:00:00",
"endTime:2017-12-09 23:59:59"),
));
$resp = curl_exec($curl);
$status_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
echo $resp;
echo "<br>$status_code";

Understanding API and how to send proper CURL request

I am trying to figure out how to use Pin Payments API, function get charge.
https://pin.net.au/docs/api/charges#get-charge
As you can see they provide an example of the request using CURL
curl https://test-api.pin.net.au/1/charges/ch_bZ3RhJnIUZ8HhfvH8CCvfA -u your-secret-api-key:
I am just not sure how do I convert that to PHP, how do I pass my API key and how to pass charge ID so that the URL understood by the server.
Please help me comple the code below:
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://test-api.pin.net.au/1/charges/ch_bZ3RhJnIUZ8HhfvH8CCvfA',
));
$resp = curl_exec($curl);
curl_close($curl);
Look up the u command line parameter: http://curl.haxx.se/docs/manpage.html
It represents the username and the password being used for the request.
Look up curl_setopt(). CURLOPT_USERPWD is the option for setting these credentials:
curl_setopt($curl, CURLOPT_USERPWD, 'apikey:');
// or
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://test-api.pin.net.au/1/charges/ch_bZ3RhJnIUZ8HhfvH8CCvfA',
CURLOPT_USERPWD => 'apikey:'
));
Please pay attention to the trailing colon! It separates the username from the password, which is empty in this case.

Setting Request Cookies in Redirect saved in cURL CookieJar File

I'm working on a project where I am using an api to interface with an ecommerce store on a separate site. I am able to add items to a basket through the api, and use cURLS CookieJar to save state. To checkout, I want to simply want to link to the actual checkout process on the main e-commerce site. I need to be able to get the cookies stored in the CookieJar to be sent along with the redirect request however.
I attempted to use cURL to grab the cookie and then follow a redirect, but I misunderstood how it works. Instead of redirecting the browser, it issues a new cURL request based on the 302 redirect.
$curlopt = array(
CURLOPT_COOKIEJAR => xxx, // this is the path to the cookie file
CURLOPT_COOKIEFILE => xxx, // this is the path to the cookie file
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_AUTOREFERER => true,
CURLOPT_URL => 'http://mydomain.com/redirect_to_ecommerce_checkout.php'
);
$ch = curl_init(); // run curl
curl_setopt_array($ch, $curlopt);
curl_exec($ch);
curl_close($ch);
This does seem to send the correct cookies to the ecommerce page, the problem is the browser doesn't redirect, instead it renders out the HTML from the main ecommerce site on my domain.
How can I set the request cookies and actually perform a redirect?
Thanks in advance.
I think you just need to tell CURL to give you the headers and not to follow the redirect. Then, you can parse for the "Location:" header. Something like this:
$curlopt = array(
CURLOPT_COOKIEJAR => xxx, // this is the path to the cookie file
CURLOPT_COOKIEFILE => xxx, // this is the path to the cookie file
CURLOPT_FOLLOWLOCATION => false, // <--- change to false so curl does not follow redirect
CURLOPT_AUTOREFERER => true,
CURLOPT_URL => 'http://mydomain.com/redirect_to_ecommerce_checkout.php',
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true // Return transfer string instead of outputting directly
);
$ch = curl_init($url);
curl_setopt_array($ch, $curlopt);
$response = curl_exec($ch); // save response to a variable
curl_close($ch);
// try to find Location header in $response
preg_match_all('/^Location:(.*)$/mi', $response, $matches);
if (!empty($matches[1])) {
header("Location: " . trim($matches[1][0]) );
exit;
}
else {
echo 'No redirect found';
}
Note I set CURLOPT_FOLLOWLOCATION => false, CURLOPT_HEADER => true, and CURLOPT_RETURNTRANSFER => true and then inspected the curl_exec() response that I saved in $response.
You could also try:
header("Location: " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);

Login to website using PHP and get text from page

I am trying to login to a website and grab content from a page you must be authenticated to see. I have done some research and have seen some examples using both cURL and stream_context_create but I cannot get either way to work. I have the url for the page to login to, and the page that contains the data I need to get. Your help is much appreciated!
Here's what I'm working with:
<?php
$pages = array('home' =>
'https://www.53.com/wps/portal/personal',
'login' =>
'https://www.53.com/wps/portal/personal',
'data' =>
'https://www.53.com/servlet/efsonline/index.html?Messages.SortedBy=DATE,REVERSE');
$ch = curl_init();
//Set options for curl session
$options = array(CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)',
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_HEADER => TRUE,
//CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_COOKIEFILE => 'cookie.txt',
CURLOPT_COOKIEJAR => 'cookies.txt');
//Hit home page for session cookie
$options[CURLOPT_URL] = $pages['home'];
curl_setopt_array($ch, $options);
curl_exec($ch);
//Login
$options[CURLOPT_URL] = $pages['login'];
$options[CURLOPT_POST] = TRUE;
$options[CURLOPT_POSTFIELDS] = 'uid-input=xxx&pw=xxx';
$options[CURLOPT_FOLLOWLOCATION] = FALSE;
curl_setopt_array($ch, $options);
curl_exec($ch);
//Hit data page
$options[CURLOPT_URL] = $pages['data'];
curl_setopt_array($ch, $options);
$data = curl_exec($ch);
//Output data
echo $data;
//Close curl session
curl_close($ch);
?>
Cheers,
Anthony
Anthony, some time ago I had to build something like that. What you need to focus on, is on the cookies.
Curl handles cookies, what you need to do is to make sure you login first, and in the same connection load the data. I you can't use the same connection, you can use the opts CURLOPT_COOKIE or CURLOPT_COOKIEFILE to help you. More info on that: http://ar2.php.net/manual/en/function.curl-setopt.php
If you have a look at How to post data in PHP using file_get_contents? you probably get what you need.
(I guess you would need to do the same post as when you log in and continue the session from there)
Edit (as response to question below)
In the first request the client will respond with some cookie after the login. This cookie must you set as a header in the second request.
If you get 500 errors it might be that the server is rejecting your request as you do not send sufficient headers to it. It's not uncommon to reject you. Try the following:
$opts = array('http' =>
array('method' => 'Get',
'Header' => "Host: www.someserver.com\r\n".
"User-Agent: Mozilla\r\n",
'user_agent' => 'Mozilla'));
$context = stream_context_create($opts);
$fp = fopen('http://www.someserver.no', 'r', false, $context);
fpassthru($fp);
fclose($fp);
... what headers that you might need to set will vary from server to server.
You are using the login fields ids instead of names:
$options[CURLOPT_POSTFIELDS] = 'uid-input=xxx&pw=xxx';
should be
$options[CURLOPT_POSTFIELDS] = 'UserName=xxx&Password=xxx';

Categories