How to post from php with cookies? - php

How can I make a post request using cookies from php.
My php code:
<?php
$time_start = microtime(true);
$id=$_GET[id];
$data = http_build_query( array ('act' => 'load_friends_silent', 'al' => '1', 'gid'=>'0' ,'id'=>$id) );
$opts = array(
'http'=>array(
'header'=>"Cookie: something=asdaefefe",
'method'=>"POST",
'content' => $data
)
);
$context = stream_context_create($opts);
print $context;
$contents = file_get_contents('http://vkontakte.ru/al_friends.php', false, $context);
$fil=fopen("./".$id."ne.txt","w");
echo '<br><br>'.$contents;
fputs($fil,$contents);
fclose($fil);
chmod("./".$id."ne.txt", 0777);
$time_end = microtime(true);
$time = $time_end - $time_start;
echo "<br><br>execute time $time seconds\n";
?>
But this code won't work on the server; cookie not sent.

[EDIT]
To use PHP to post to a page that the user will NOT navigate to, you can use CURL:
http://davidwalsh.name/execute-http-post-php-curl
Where in the example, you set $fields to your cookie values:
$fields = array(
'lname' => urlencode($_COOKIE['last_name'] ),
'fname' => urlencode($_COOKIE['first_name'] ),
...
);
[EDIT AGAIN]
By your newly posted code it looks like you are trying to create a cookie on the page that you are posting to. First of all, creating cookies for other websites would seem to be a big security risk, so I'm 99.9% certain that this has never been nor ever will be possible. Secondly, PHP is not a browser and can't store cookies for other sites...so even if your post created a cookie, the user's browser would not have that cookie. All you can do is post 'something'=> urlencode('value'), and then the page you are posting to will have to create the cookie on their end. However, since PHP can't hold cookies since it's not a browser, this would be pointless.
If you want the user's browser to have a cookie, then you need to use something like jQuery's $.post. Using jQuery's post() method will use the user's browser to go to the page and post data. The page that gets the posted data can then create a cookie on the user's browser.
[Read These] they may contain some info for you. Is this what you're trying to do?
Simulating a cookie-enabled browser in PHP
Simulating a POST with PHP & cURL
It does sound like CURL should be able to mimic a browser's cookie capabilities...so you might be able to send cookie data, though, as I said, you woudln't be able to set the user to those cookies or anything...since I'm not sure of your purpose, that makes an answer harder:
http://php.net/manual/en/function.curl-setopt.php

Read this, maybe it will help. http://www.w3schools.com/PHP/php_cookies.asp

Related

Do someting if user does not interact after some time - PHP

I`m building a whatsapp bot, the bot is fully operational, but I want to do a API call if user does not interact with the api after some time. I tryed to do with session, but is not working, I tryed the following code.
session_start();
//**my bot code**
$minutesBeforeSessionExpire=30;
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > (2))) {
$data2 = [
'phone' => $_SESSION['phone'],
'body' => 'Hello, Andrew!',
];
$json2 = json_encode($data2);
$options2 = stream_context_create(['http' => [
'method' => 'POST',
'header' => 'Content-type: application/json',
'content' => $json2
]
]);
$result2 = file_get_contents('api_call', false, $options2);
session_unset(); // unset $_SESSION
session_destroy(); // destroy session data
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity
Unfortunately for you, "any API" is purely "server side." Therefore, it cannot "react" when anyone "fails to reply." The only thing that it can do is, when presented with [any ...] subsequent request, to say: "So sorry, too late!"
The key point being that the response is reactive, not proactive.
In order to “do something” when a user doesn’t interact, there must be something that interacts with the user. This is typically either a client side script, websockets, signal R. It doesn’t just happen naturally, in fact quite the opposite, naturally the server totally forgets about an incoming request as soon as it is done with it.
For those who find this question, I solved my issue by storing the user last interaction on my db.
After that I created a cron on my cpanel to run the update code, and everything ran as expected.

Log in to an external website and redirect it as a logged-in user

great pleasure someone helps me with the following question, you will see I want to create a site that stores the accounts of the external pages, so that when they enter the user and the password in my application, this one realizes the login in the external web and then redirect the page how logged in users. My question is this, is it possible to do that? I wanted to try it with guzzle, but it could not, then I tried goutte, but I got an error that did not detect the fields, what could I do? Thank you
So users will need to share their username and password with you and you'll be storing that in your DB, and it'll need to be plain text or in a way that is easily converted back into plain text. This is a BIG RED FLAG.
If there is some legitimate reason why you'd be doing this, I'd suggest working with a CookieJar in Guzzle. You could POST a login with the user credentials, and store the resultant cookie, then send that in the headers with any subsequent request for that user.
Some rough code to give you an idea:
$client = new GuzzleHttp\Client;
$filename = $somePath . '/cookies.json';
$jar = new GuzzleHttp\Cookie\FileCookieJar($filename);
// Login
$url = 'http://some_login_url';
$body = [
'user' => $someUser,
'pass' => $somePassword
];
$response = $client->post($url, ['cookies' => $jar, 'body' => $body]);
// Make sure the response is valid here
$jar->save($filename);
// Retrieve a private page for a user
$url = 'http://private_page_url';
$response = $client->get($url, ['cookies' => $jar]);
// Make sure the response is valid here
$html = (string) $response->getBody();
// Do scrapy stuff with HTML
Clearly, this would need a bit of work to make it useful.

Authenticate with Wordpress cookie through API from a subdomain

I want to access the current logged in Wordpress user in a separate Laravel installation.
Wordpress is running as website.com and I've got a subdomain with tool.website.com with the Laravel application (on another server but same domain).
I'm using the Native Wordpress API and created an authentication route.
The issue:
When I access the /authenticate route directly, the user ID is returned and works correctly. But when I access the route through tool.website.com false is returned..
Things I've got working:
I've created an API request which returns the user id in an API call:
add_action( 'rest_api_init', function () {
register_rest_route( '/authenticate', array(
'methods' => 'GET',
'callback' => 'authenticate',
) );
} );
The function looks like this:
$user_id = wp_validate_auth_cookie( $_COOKIE[LOGGED_IN_COOKIE], 'logged_in' );
The WP cookie is available on both the sub / main domain. I can see they are identical and toplevel.
define('COOKIE_DOMAIN', '.website.dev');
Things I've tried:
Using wp_get_current_user() to retrieve the user, this seems to need a nonce. I experimented hours and hours with the nonce approach on many different ways, but I could not get this to work (false or 0 was returned). I understand this is due to restrictions of using a nonce from outside of Wordpress.
Using the default native API approach to get the user, also needs the nonce.
Reading the https://developer.wordpress.org/rest-api/ manual, git repository & several articles / comments online.
Thinking about the OAuth approach, but I do not want users to login again as they are already logged in when they reach the tool.
Sending stuff like posts etc works without problems, so the API connection is not the problem.
I'm wondering if my approach is in the right direction. Hopefully someone can give me some guidance.
I found the following workaround:
- tool.website.com
Send the Cookies from tool.website.com to the API as post data.
$cookie_array = $_COOKIE;
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($cookie_array)
)
);
$context = stream_context_create($options);
$data = file_get_contents(self::BASE_URL . "authenticate", false, $context);
- website.com
Retrieve the cookie from Post data, and use the standard LOGGED_IN_COOKIE constant in Wordpress to select the correct one (this can be refactored to sending the correct cookie at once).
// We retrieve the cookie (which is sadly not available through the API call alone)
$the_cookie = $request->get_body_params();
// As the cookie lives at domain level, we can use the same Cookie key in the WP API and other subdomains of this domain
// The cookie key remains the same
$user_id = wp_validate_auth_cookie( $the_cookie[LOGGED_IN_COOKIE], 'logged_in' );
This solution seems steady; hopefully it will help someone. If there are other solutions, please add them in this topic; as I'm sure there must be different ways achieving this.

GET works but POST doesn't for silent login

We have 2 systems one in PHP and one in asp.net which currently require separate logins even though both use the same username/password information.
As a quick (and temporary) fix I thought I might be able to amend the PHP login page to pass the login details to the asp.net page behind the scenes so the user could be logged in automatically to both systems rather than having to enter their credentials again when navigating to a different page.
This works fine when I use a GET to pass the parameters but of course the GET parameters including the password get stored in the server log which is not a good idea.
So I would like to use POST instead, but I can't get it to work. I used the CURL-less method in How do I send a POST request with PHP? (code below) and it appears to work but the asp.net login process creates secure cookies and while they are stored if I GET the page they are not being stored when I POST to it instead.
$url = 'https://server.com/path';
$data = array('key1' => 'value1', 'key2' => 'value2');
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
var_dump($result);
I have tried something similar with CURL in the past so I know that CURL creates it's own browser context but I thought a straight POST request would work, however it seems to be behaving much the same as CURL.
Is there some way to get this to work or do I have a fundamental misunderstanding of how POST works? If so could somebody point me at a good explanation.

Cannot sent cookie with Guzzle request

I have a PHP script that needs to fetch a CSV file from an application. There is an API for the application that allows the script to lot in, which gives the script a session cookie for authentication. I then need to doa GET request to fetch the CSV file (which the API does not support).
Using curl directory works:
$c = curl_init($url);
curl_setopt($c, CURLOPT_COOKIE, 'PHPSESSID=' . $session_id_from_api);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
$csv_file = curl_exec($c);
echo $csv_file;
That fetches the CSV file using the session ID obtained from the API login and passed through a coookie.
Now, I would like to do the same thing using Guzzle, but I just get the login page back instead. This is the code I'm using:
$client = new Guzzle\Http\Client();
$request = $client->get(
$url,
[
'cookies' => ['PHPSESSID' => $session_id_from_api],
]
);
$response = $client->send($request);
echo $response->getBody(true);
That gives me the login page, so the GET to the application is not recognising the session defined by the cookie.
Is there anything else I need to do to ensure the cookie and value I specify is sent to the remote application?
Edit: looking at $request->getRawHeaders(), I see this line in the headers:
cookies: vec6nb1egvvui6op7qr7b0oqf6
That obviously isn't right. The documentation for my version of Guzzle gives this example:
// Enable cookies and send specific cookies
$client->get('/get', ['cookies' => ['foo' => 'bar']]);
which looks to me to be consistent with what I am passing to Guzzle.
Just to be clear, I am not trying to manage cookies in both directions over multiple requests, so there is no need to store any cookies. I have a cookie name and its value (from another source), and I just want to make sure that name and value gets sent to the destination for a single GET request. I'm not trying to "maintain a session", but in a way I am having a session passed to me from another part of the application (not Guzzle) and need to set my Guzzle request up to use it.
Well, this seems to work. Guzzle was not sending the cookie without being sure the domain it was sending it to was correct:
// Set up a cookie - name, value AND domain.
$cookie = new Guzzle\Plugin\Cookie\Cookie();
$cookie->setName('PHPSESSID');
$cookie->setValue($session_id_from_api);
$cookie->setDomain($domain_of_my_service_url);
// Set up a cookie jar and add the cookie to it.
$jar = new Guzzle\Plugin\Cookie\CookieJar\ArrayCookieJar();
$jar->add($cookie);
// Set up the cookie plugin, giving it the cookie jar.
$plugin = new Guzzle\Plugin\Cookie\CookiePlugin($jar);
// Register the plugin with the client.
$client->addSubscriber($plugin);
// Now do the request as normal.
$request = $client->get($url);
$response = $client->send($request);
// The returned page body.
echo $response->getBody(true);

Categories