Redis Cluster for php session and ajax call not save session - php

It was been a couple of days I've got an issue with php session (in cakePhp 4 project) with a redis cluster and ajax call that not save in session.
Use case :
I'm on a page with a session, session works perfectly. on this page there is à button that call an ajax action. On https://www.mywebsite.com ajax call https://www.mywebsite.com/ajaxAction (so no cross origin pb like I see a lot of time)
ajaxAction is very simple :
public function ajaxAction()
{
$this->disableAutoRender();
$treeId = (int) $this->request->getData('treeId');
var_dump($_SESSION['myArray']); // empty
$_SESSION['myArray'][$treeId] = true;
var_dump($_SESSION['myArray']); // array with the value
}
If I click to add an other $treeId in the session, the first debug is empty, and the second has only the new value.
When I check the session value in redis-cli, the value is not in the session.
If I put a sleep(1) after the $_SESSION['myArray'][$treeId] = true; the value is save in the session.
If I'm trying the same type of call with two simple php script (without cakePhp), it works perfectly....
Someone has a solution to understand the pb to find a solution ?
Is it from cakePhp ? Redis ? Ajax ?
Thanks for you're help
EDIT :
After another day of testing and searching a solution, the problem is only with cakephp. The only solution I've found is to make a usleep(100000); but it's not a solution of the problem for me....
EDIT 2 the return :
After analysing redis monitor, I could see that cakephp make two call to set the session during an ajax request. First save the new session, then save the old value of the session. It explains why with a sleep the new session is save after the old value.
Next step, undertand why cakephp make the two call of the session set (outside cakephp, there is only on cool in case of ajax request....)

Related

Saving PHP Session variables to local variables

Im having a big problem, i am generating content with my php script. I pass some text-input to my generating script. This script is putting all text-inputto the $_SESSION variable.
For example :
$_SESSION[text1] = $text1;
$_SESSION[text2] = $text2;
and so on...
In the generated page i take those $_SESSION variables and put them to local variables.
For example :
$text1 = $_SESSION['text1']
$text2 = $_SESSION['text2']
and so on...
But after i destroy the session (Cause of login/logout system) all the content on the generated site is gone. Only the HTML tags are still there. So that means for me, all session variables get empty after destroying the session.
My question now is how do i save those session variables without loosing them after a session_destroy();?
Ps: Im using a MySQL-Database but im not so talented with it.
Session var are destroyed after session_destroy, it is how it works. You can save what you want in mysql DB, in a file (json format), mongodb, in memcached, in redis ...
You can also use cookies for simple and non secure var.
A very simple thing is to save it in a file :
file_puts_content('filename.json',json_encode($_SESSION));
and to get it back
$_SESSION=json_decode(file_gets_content('filename.json'),true);
But it's much better to do it with a database.
A solution could be to store them in the MySQL Database.
Use PDO connector to insert rows in your tables : [Doc Here]
And Insert like this :
INSERT INTO my_table(`var1`,`var2`,`var3`) VALUES($val1,$val2,$val3);
What is the context of the application ?

Updating $_SESSION variable - PHP

I have a script in php that does some operations before insert the results into my table, but I'm trying to prevent the execution twice or more of the same script if i open it in more than one tab in my browser, I'm working to do a kind of trick to do this, for this I'm using sessions, I got a specific session variable that is updated when I run the script but my question is..
if I got something like this
session_start();
if (isset($_SESSION['lock'])) {
if ($_SESSION['lock'] === false) {
$_SESSION['lock'] = true;
}
}
that code is into a file that is executed with ajax request, once the variable has been updated with a new value it will be update globally?, I mean I have open two tabs with the same page (tab1 and tab2) after execute the script in tab1 when I do the same in tab2 the value $_SESSION['lock'] will be true or false?, I hope this explanation to be good, thanks.
NOTE: both tabs were opened at same time
Yes, changing $_SESSION is a global change for that particular user. But note that changes to $_SESSION are NOT pushed out to multiple windows "live". Only on subsequent hits in ANY window/tab will the new value have a chance to affect those tabs/windows.
Yes, sessions are bound to a unique User, so they are spreaded over tabs. Why don't you just test it though?

Why is my PHP $_SESSION cleared when doing an AJAX Post?

I'm trying to get some values from my $_SESSION variable but it seems to be cleared everytime an AJAX request is initiated.
I have pasted the code below, any help much appreciated :
/*
* The input request from angularjs
*/
$data = file_get_contents("php://input");
$data = json_decode($data, true);
switch( strtolower($data['action']) ) {
case 'products': getAllProducts($data['fields']);
break;
default : echo json_encode(array('success' => false));
}
//fb is a firebug debug function, prints PHP vars to console.
fb($_SESSION['var'); //when loading the php file the first time $_SESSION is set
UPDATE
I'm using AngularJS for my AJAX calls, it works great but now I want to read data from my $_SESSION variable and all I get is an empty $_SESSION. Does this have anything to do with my file_get_contents("php://input");
SOLVED
I found the problem, the previous developer did not take into account that one might desire to include files from 2 levels deep :) As such, I scanned through the PHP error logs and saw that a previous script was not loading - this particular script was included with the session_start and $_SESSION variable values.
Checking the error logs will be my first priority from now on
I found the problem, the previous developer did not take into account that one might desire to include files from 2 levels deep :) As such, I scanned through the PHP error logs and saw that a previous script was not loading - this particular script was included with the session_start and $_SESSION variable values. Checking the error logs will be my first priority from now on

PHP/Smarty - Random Session data loss between 2 pages

I'm facing the weirdest issue I've ever seen with PHP. I will try to be really exhaustive because each detail can count.
I have 3 PHP pages, and their HTML is generated using Smarty. They all call session_start() at their top.
the first page can be heavy to load, it displays a big amount of clickable pictures that are previews of PHP complex objects
if a picture is chosen it leads to the second page with a specific URL.This page will generate a PHP object related to the URL info (so this page does not need info from previous page to work. If you copy-paste this URL at anytime it will work). This object will be stored into $_SESSION with a unique id.
the third page is included as an img src in the second page's HTML code (generated with Smarty). This is a PHP page having the object's session id in URL parameter and reading the object's info in $_SESSION, creating it's image preview and turns into an image with header('Content-type: image/jpeg').
To sum up :
heavy first page => second page creating and storing a PHP object into $_SESSION => third page, included in second page's HTML code, searching for this object and creating a preview.
The problem is, sometimes, this third page is trying to load the object in $_SESSION and it's just not there !
Some facts :
the problem never occurs when the second page is loaded as a stand-alone with its own URL
the problem only occurs randomly when the heavy first page starts loading images and we furiously click on one of the first ones to appear
whatever the situation is, if I dump my $_SESSION variables at the very end of the second page I can ALWAYS see the generated object in my session
So it seems that the issue is located between the very end of the second page and the beginning of the third, but all of this related to the activity of the first one !
All I know is that it is linked to a fast navigation between pages.
I've tried almost everything :
session_write_close() everywhere it's possible (at the end of my pages before/after smarty display, then at the beginning before session_start())
add exit() at the end of my scripts
even sleep(1) at the beginning of the third in case session close operation needs more time
Nothing works. I have no more clues ... Maybe Smarty ? Maybe some odd PHP session behaviour named bug #4454 somewhere ?
Thanks a lot in advance for helping me with this.
Edit : piece of code after serialize() chat
/* ===== Page2.php ===== */
/*creating object $card and setting some values ...*/
/*calling the function that gives the card preview*/
$assigns['front'] = $card->getPreviewURL();
/*other stuff ... assign $assigns to smarty ... etc*/
/* ===== Card object class ===== */
function getPreviewURL()
{
$_SESSION['products'][$this->getObjectId()] = serialize($this);
$url = '/page3.php?s='.$this->getObjectId();
return $url;
}
/* ===== Page2.html ===== */
img src="{$front}" alt="toto"
/* ===== Page3.php ===== */
/*getting id value and reading session*/
if(!empty($_GET['s'])) {
session_write_close();
$session = new Session;
if(!empty($_SESSION['products'][$_GET['s']])) {
$product = unserialize($_SESSION['products'][$_GET['s']]);
}
else {
log('$_SESSION[products]['.$_GET['s'].'] does NOT exist');
header("Status: 404 Not Found");
exit;
}
}
and when bug occurs, I get :
page2.php debug log :
Session value : [o20aee110e0853e74da4d17c9b7ab3075]=>O:8:"Postcard":19:{s:4:"tmpl";O:16:"PostcardTemplate":20:{s:2:"id";s:3:"152";s:2:"or";i:0;s:3:"ord";s:2:"14";s:11:"description";s:0:"" ... etc
page3.php debug log :
$_SESSION[products][o20aee110e0853e74da4d17c9b7ab3075] does NOT exist
Probably, the problem is, that PHP tries to unserialize your object but cannot find the class definition.
You can do one of the following two things:
serialize() the object manually before you put it into the session and unserialize() it after you loaded the class definition.
Or: Use autoloading.

Setting session_id unreliable when using flash to send data

I'm using PHP version 5.3.2 on both my local development server and remote web server.
I'm trying to use uploadify to upload several files to the server. In the receiving script, I would like to use data stored in the session, however because uploadify sends files to the script using flash it doesn't send the session cookie.
The workaround for this problem is to get uploadify to GET or POST the session id to the script, however I'm finding this very unreliable.
In my script I have the following:
<?php
ini_set('session.use_only_cookies', FALSE);
ini_set('session.use_trans_sid', TRUE);
session_name('SESSNAME');
session_start();
print_r($_SESSION);
The script url is something like script.php?SESSNAME=sessionid and I have tried using transparent session ids as above and also manually setting the id using session_id($_GET['SESSNAME']).
This always works when accessing the script directly with the browser and sending the current session id along, even if I manually delete the session cookie. It also always works with uploadify on my local server. However when using uploadify on the remote server, it works about 20% of the time, completely randomly. There is no pattern. It seemed to work with greater frequency when I added
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 1);
to the script, however this may have been just coincidence.
Local server info: http://www.dur.ac.uk/n.r.brook/info_local.php
Remote server info: http://www.dur.ac.uk/n.r.brook/info.php
Some speculation...
Doing some digging around and looking at the headers the script is receiving, I think I may have determined the issue.
You need to send the session id when using uploadify because flash does not send cookies when using the FileReference.upload() (I think!) method. However, as well as the session id, in load balanced environments (such as the remote server) there is also the BALANCEID cookie which determines which server the user is currently working with. Flash doesn't send this cookie so the load balancer sometimes sends the request to a different server, and on this server the session does not exist.
I have tested this behaviour by setting a session variable after I have printed the session. Doing this and repeatedly sending files exhibits the issue - at first I get an empty array, but a few repeats in the variable starts appearing.
So, if the above is all true, then my question is what can I do to get flash to send this data with the upload so the load balancer knows which server to use? Or is this a lost cause?
The answer?
After further research, I found the following post - http://swfupload.org/forum/generaldiscussion/977
This suggests there is no way cookies can be sent with FileReference.upload() and therefore uploadify cannot be used with load balanced servers if you want to use session data. However, I think I will now attempt a solution which saves data linked to the session id to a file. The uploadify receiving script can open this file and pull out the required data.
This is my first experience working with anything Flash based, it has not improved my opinion of the technology!
My solution to this problem is:
In the 'upload' page:
file_put_contents($some_folder.'/'.session_id(), serialize($just_the_vars_you_will_be_using));
In your javascript that loads uploadify:
var start = document.cookie.indexOf("PHPSESSID=");
var end = document.cookie.indexOf(";", start); // First ; after start
if (end == -1) end = document.cookie.length; // failed indexOf = -1
var cookie = document.cookie.substring(start+10, end);
$('#fileInput').uploadify({
'uploader' : 'uploadify.swf',
'script' : 'uploadify.php',
'cancelImg' : 'cancel.png',
'auto' : true,
'multi' : true,
'scriptData': { SESSID : cookie }
});
In the script that receives the files:
$vars = unserialize(file_get_contents($some_folder.'/'.$_POST['SESSID']));
If you want to write back to the 'session' in this script, at the end:
file_put_contents($some_folder.'/'.$_POST['SESSID'], serialize($vars));
As far as I know, there shouldn't be any security issues associated with this, as you will only be using a handful of variables stored in the file (I only store an incrementing value and a temporary file path). Make sure there is an index.html in $some_folder to prevent file listing.
There is a way you can use cookies when sending from flash.
Cookies is needed for php to find the session storage id. The value that is stored in the cookie is actual the session id and the cookie name is in most cases the session name.
To get the session in php can´t be done by typing $_SESSION['name'] but you can make your own session library that you include. This will let php get all of the nassery values and you can continue.
Here is a session library that I put together in php:
function SESSION_OPEN($PATH,$NAME){
global $SESSION_PATH, $SESSION_NAME;
$SESSION_PATH=$PATH;
$SESSION_NAME=$NAME;
return(true);
}
function SESSION_CLOSE(){
return(true);
}
function SESSION_GET($ID){
global $SESSION_PATH, $SESSION_NAME;
$STR_PATH="$SESSION_PATH/USES_".session_id()."_$ID";
if($RESOURCE = #fopen($STR_PATH,"r")){
$CONTENT = #fread($RESOURCE ,filesize($STR_PATH));
return($CONTENT);
}else{
return(false);
}
}
function SESSION_PUT($ID,$VALUE){
global $SESSION_PATH, $SESSION_NAME;
$STR_PATH="$SESSION_PATH/USES_".session_id()."_$ID";
if($RESOURCE = #fopen($STR_PATH,"w")){
fwrite($RESOURCE , $VALUE );
return(true);
}else{
return(false);
}
}
function SESSION_DEST($ID){
global $SESSION_PATH, $SESSION_NAME;
$STR_PATH="$SESSION_PATH/USES_".session_id()."_$ID";
return(#unlink($STR_PATH));
}
function SESSION_GC($MAX_EXECUTION){
return(true);
}
session_set_save_handler("SESSION_OPEN","SESSION_CLOSE","SESSION_GET","SESSION_PUT","SESSION_DEST","SESSION_GC");

Categories