How to unserialize session data in a custom handler - php

I have used sessionHandlerInterface to save the session in database. Everything works fine. but I want to get all the serialized data from the database like
SELECT data FROM session;
and want them to decode the data when i output those.
i have tried using session_decode() which is manipulating $_SESSION array itself which is causing trouble. I just want to get the serialized data and return the decoded data.
This is the sample session data saved in database in data column
fb_422782977793963_code|s:216:"AQAVKa4Q8sOuioW75V9Ls-cDUEizgJDX5ZkRVLArDlroFvvhasdwKvbyzKEwiMVrN7nc5ghMaw0W67jQu5kt_sc_Edm9sABzB5PakdkUpXr52AViTOltPfPBQHM9T-JoGOQ4gasdbssC8Xt93NKFvdV7XRZ7ZYGZqIsu5SFpfFBHK_hNGDdRVbnbe_xUZVP9WI4h0jDy";fb_422782977793963_access_token|s:111:"AAAGAhasdaAKL7hAvXRv6FHUj1Tk24r7j4NqDwWWUzmXDZA2Igsb1pHjuP4jbBRNKfeYzutm0MFmgxuKPg1n0NEbvZAXM3bwoNZBiZCgZDZD";fb_422782977793963_user_id|s:15:"100004835469598";picture|s:61:"http://m-static.ak.fbcdn.net/rsrc.php/v2/yo/r/sdIqmHJn-SK.gif";
It works fine with normal session handling, it reads and writes session to database as it should.
I want to get all the data of active sessions. if i use SELECT data FROM sessions. it returns the above session data(encoded) i want to get the decoded data of it.

The PHP serialize and unserialize functions can not be used to serialize and unserialize session data. Even if (by default - and only by default) the serialization might look similar, there is an important difference to those two functions that care about a single variable contents only:
Those [sessions] are a list of serialized values with their variable name.
(from: Serialized README)
So you would need to create your own a session_unserialize function that is able to decode the string (e.g. via session_decode) which is returned from your database. Take care that this needs everything in there, e.g. if the session contains serialized objects, the class definitions needs to be loaded.
An exemplary session_unserialize function could look like (adopted from: a session related answer):
function unserialize_session($data) {
$hasBuffer = isset($_SESSION);
$hasBuffer && $buffer = $_SESSION;
session_decode($data);
$session = $_SESSION;
$hasBuffer ? $_SESSION = $buffer : unset($_SESSION);
return $session;
}

Related

PHP session store data before flush

I am storing some data in variables like this,
$dbs_office = $request->session()->get('dbs_office');
$reference = $request->session()->get('reference');
$request->session()->flush();
return view('confirmation', ['ref' => $reference, 'dbs_team' => $dbs_office]);
I was hoping that by storing some of the session data in their vars I would be able to persist the data past the flush, however the vars are empty when I check. Is there a way to store these bits of data for use in a view, but remove the session data totally?

Custom session save_handler overwerites current saved data in database

So I finally managed to save some session data in to the database.
Now a new problem arises. When I load the page once all data is being saved.
When I reload the page and I write something to the session all data that's already in the session is being replaced with this new data. This means that with each load all the data is being replaced for new data. This is giving me problems because I'm saving a order_id into the session when there is no order_id present in the session.
This is the code that writes the data into the database. And yes it says replace into. But because this is a custom handler how can i actually append data to this current session with out renewing everything. Also how can I replace old data for new data witch is already present in the session.
The code that handles the writing to the database.
function _write($id, $data) {
$access = time();
$id = $this->session_db->real_escape_string($id);
$access = $this->session_db->real_escape_string($access);
$data = $this->session_db->real_escape_string($data);
$sql = "REPLACE INTO sessions VALUES ('$id', '$access', '$data')";
return $this->session_db->query($sql);
}
Is there something that i can do to put all the data directly after session_start() in the session variable so it always has all the data and doesn't overwrite the data with a single value when I do something like:
$_SESSION['LAST_ACTIVITY'] = time(); ?
EDIT: Also when I try to echo the session directly after the session_start();
It gives me there error
Warning: session_start(): Failed to decode session object. Session has been destroyed in /var/www/vhosts/url/httpdocs/index.php on line 13
Is there something wrong with the serialized string I don't understand why it is giving me this error.
Thanks in advance, some help will be appreciated.
Ok so now everything is working. I kinda feel embarrassed for saying what the problem was. So ok the problem and the solution.
The problem was that the session serialized data was way to long for a regular text field in the database. My string was over 500.000 characters long regular text field in database supports until 65.000+ characters.
So I changed the field from "TEXT" to "LONGTEXT" now it has enough space to save the string. And now everything works properly.
Everybody thanks for your time so far.

How to unserialize codeigniter session data from database

I wan to use CI session in a external script and I got following data from database.
__ci_last_regenerate|i:1446535049;ci_UserID|s:1:"2";ci_UserName|s:24:"example#xyz.com";logged_in|b:1;
I have tried unserialize and unserialize(base64_decode($data)) but I am fail yet.
Please help to extract this data.
I got the solution here
So I have used session decode
session_decode('__ci_last_regenerate|i:1446535049;ci_UserID|s:1:"2";ci_UserName|s:24:"example#xyz.com";logged_in|b:1;');
So session decode stored all the encrypted data in normal php session.
Which I can access using: echo $_SESSION['ci_UserID'];
Well guys thanks for the help
If this is a session variable, you can use CodeIgniter's own session library. Consider the following code (in a controller):
$this->load->library('session'); // load the session library
$session_data = $this->session->all_userdata(); // get all session data
print_r($session_data); // print and get the corrresponding variable name, e.g. "item"
$var = $this->session->userdata('item'); // pick one that suits your needs, e.g. item
Sorry, I have read "the external script" only after having posted the code. This obviously only works in the CI framework.
For an external script you may need to have a closer look. The variables are separated by ";" and "|" and then serialized, so this might work (not tested):
$row = explode(';', '__ci_last_regenerate|i:1446535049;ci_UserID|s:1:"2";ci_UserName|s:24:"example#xyz.com";logged_in|b:1;'); // load the database row
$userid = explode('|', $row[1]);
$userid = unserialize($userid[1]); // now $userid holds the value "2"

CodeIgniter flash data working locally but not on server

Hello CodeIgniter users.
I have a problem with flash data and I would like some help. My CI version is 2.1.4.
I am using CI flash data to store data temporarily for a form that consists of multiple pages. Data entered on each page is stored so it can be accessed on the next pages and finally all data is entered int the database.
Now to keep data stored through multiple pages, instead of only one, I extended the Session class with the following function:
function keep_all_flashdata($prefix = '')
{
$userdata = $this->all_userdata();
foreach ($userdata as $key => $value)
{
if (strpos($key, ':old:' . $prefix))
{
$new_flashdata_key = str_replace(':old:', ':new:', $key);
$this->set_userdata($new_flashdata_key, $value);
}
}
}
This function preserves all flash data (or optionally only flash data that starts with a certain string) for another redirect. It is similar to the keep_flashdata function except for the fact that it works for multiple items without requiring their exact name.
After calling this function, both :old: and :new: keys are stored in the session data. Then after a redirect, old keys are removed and new keys are set to old. Then, if there's another page, I call keep_all_flashdata() again and so on until the last page.
This works fine when I'm working on my local WAMP server, but on my actual server, all flashdata just gets removed after a redirect, even if it has :new: in the key. I confirmed my keep_all_flashdata() function works by checking the contents of session->all_userdata() and everything looks as expected.
I am using some AJAX calls, but they should not erase flash data (a known issue) as I've prevented this with $this->CI->input->is_ajax_request() before flashdata is cleared (in the sess_update() and _flashdata_sweep() functions).
Is this a bug in CodeIgniter or am I doing something wrong? Any help is appreciated.
I think your if statement is causing the problem. I'm assuming that ":old:" or ":new:" is used as prefix for every key you store in a session?
strpos() returns the position of where the needle exists so that would be 0 when checking a key with the prefix ':old:'. That's intended as old flashdata needs to be removed. I tested the following piece of code:
$flashDataKey = ':new:myKey';
die(var_dump(strpos($flashDataKey, ':old:')));
Which returns false as expected since the needle was not found. Resulting in not storing the flashdata as ':old:' and keeping it for the next request.
I'm not sure why this is working on your localhost. You should change your if statement to:
if( strstr($key, ':new:') !== false)
Now only keys containing the string ':new:' will pass and everything else will return false. Hope this helped!

store objects in $_GET

how can i store an object in the $_GET array in PHP. i want to pass an object containing database information from one page to another page via the $_GET array, so there would be no need to access the database again.
To pass any sort of object, you'd have to serialize it on one end, and unserialize it on the other end.
But note that this will not work for database connections themselves : the connection to the database is automatically closed when a PHP script ends.
You could pass some connection informations, like login, host, or stuff like that (but that would not be a good idea -- quite not safe to expose such critical informations !) ; but you cannot pass a connection resource.
Really, you should be passing data from one page to another via the $_SESSION variable instead, if possible. That is what sessions are for. Ideally just store an id in the session and look up the data on each page. If you do use $_SESSION then it is as simple as ...
$_SESSION['myarray'] = $myarrayobject;
$_SESSION['someotherthing'] = 42;
If you have to use $_GET, then I would recommend just passing an id of some kind, then re-looking up the data on each page refesh.
Keep in mind, it would be easy for a malicious user to change the values that are sent via $_GET between pages, so make sure there is nothing that can be abused in this information.
You would need to serialize it to text (possibly using json_encode), then generate a URL that included it in the query string (making sure that it was urlencoded)
That's very bad idea.
Database were invented to serve each request, while query string were designed to pass only commands and identificators, not tons of data between browser and server
Instead of using get, another possibility to pass something from one page to another is to use the $_SESSION array and then to unset that variable on the other side whenever you're done with it. I've found that to be a pretty good way to do this.
Like everyone else has said though, passing database information can be a bad idea, assuming the information you're passing isn't something like username, first name, etc. If that's what you're passing when you say "database information" then I would store all that stuff in the $_SESSION variable and then destroy their session when they log out. Don't store the entire connection or something.
As has been said before you should avoid (mis-)using GET parameters as a "cache" for overly complex and loooong data.
On the other hand your question is vague enough to assume that you want to transmit only a few values. And your "second" script needs nothing else from the database, in fact it might not even have to check if those values came from a database at all.
In this case extract the values from your database result and append them as parameters to the url. Try to make the parameter list as simple as possible but yet unambiguous. http_build_query() can help you with that.
But keep in mind that you want to keep GET operations idempotent as described in http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html.
if ( isset($_GET['a'], $_GET['b'], $_GET['c']) ) {
// this doesn't care about the values in the database at all.
echo 'product: ', $_GET['a'] * $_GET['b'] * $_GET['c'], "\n";
}
else {
$pdo = new PDO("mysql:host=localhost;dbname=test", 'localonly', 'localonly');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// let's make it a self-contained example (and extra constly) by creating a temproary table ...
$pdo->exec('CREATE TEMPORARY TABLE foo (id int auto_increment, a int, b int, c int, primary key(id))');
// ... with some garbage data
$stmt = $pdo->prepare('INSERT INTO foo (a,b,c) VALUES (?,?,?)');
for($i=0; $i<10; $i++) {
$stmt->execute(array(rand(1,10), rand(1,10), rand(1,10)));
}
foreach( $pdo->query('SELECT a,b,c FROM foo', PDO::FETCH_ASSOC) as $row) {
printf('%s<br />',
http_build_query($row),
join(' * ', $row)
);
}
}

Categories