Looping Through All a Server's Sessions in PHP - php

Is there a way in PHP to get a list of all sessions (and the variables within each) on the server?
Basically, we have a maintenance function which needs to know which users are currently logged into the site. We already store data for each user in a session variable, but I am hoping that I can loop through each of these sessions and pluck out the data I need.
MY PHP is very limited (I am a .Net developer ussually) but if anyone knows if this is even possible (and how to do it) I'd be very grateful. I googled this, and the results I found tended to inidcate that it WASN'T possible, but I find this very hard to accept.
Still, If you can't you can't but I thought my buddies on StackOverflow could give me a definitive answer!

PHP stores session data for each user in a temporary folder on the server. This folder is defined in the php.ini configuration file under the variable session.save_path. Locate this value from within your php.ini file, or alternatively, create a php file with:
<?php echo "Session Save Path: " . ini_get( 'session.save_path');?>
as it's contents, and open the file in your browser.
Once you find the save path for the session data, open up that folder and you'll notice a fairly simple structure. All sessions are stored in the format: sess_$SESSIONID .
Session data is serialized before being stored on disk. As such, objects stored in the session file would have to be deserialized before being usable. However, if you're using plain text, which is stored as-is, to store your session data (ex. $_SESSION['userid'] = 1234) to store information about your users, it should be easy enough to parse out the data you're looking for from within the files.
One more thing ... I haven't looked into it, but it appears as though the session ID that appears in the filename corresponds directly to, for instance, the name of the PHPSESSID cookie stored on the user's computer. So, with this in mind, it may be possible to loop through the files within the temporary session directory, acquire all the $SESSIONID values, set the current session ID using session_id($SESSIONID), start a session with session_start() and access the data you need through PHP without having to parse the contents files themselves. Can anyone confirm whether or not this would be possible?
Edit: Adjusted post to match Itay's comment.

This will get you the data for all sessions, stored in an array and indexed by session id:
<?php
$allSessions = [];
$sessionNames = scandir(session_save_path());
foreach($sessionNames as $sessionName) {
$sessionName = str_replace("sess_","",$sessionName);
if(strpos($sessionName,".") === false) { //This skips temp files that aren't sessions
session_id($sessionName);
session_start();
$allSessions[$sessionName] = $_SESSION;
session_abort();
}
}
print_r($allSessions);

Here's a more succinct way to get a list of sessions via the stored files:
<?php
print_r(scandir(session_save_path()));
?>

I used the #mgroat method in the ajax call, but there is a problem in the header of the HTTP response that the Set-Cookie header appears multiple times and jQuery reports an error:
Set-Cookie header is ignored in response from url:
mysite.com/admin/ajax/main_ajax. Cookie length should be less
than or equal to 4096 characters.
The solution is to add header_remove("Set-Cookie") right after session_start().

Related

PHP change content of session cookie file

I´m not sure If I am making a mountains out of molehills ...
I´ve two Servers A + B. I know on Server A exists a PHP Session with a session cookie. I know further in one of the session files (stored in var/lib/php5) exists a unique value like:
$_SESSION['name'] = "1_colourXY"
I can identify this cookie file with php by searching the dir/ files for this value (f.e.: file sess_489b9515146e7390ac03b5dabf36b70e).
I now want Server B to be able to tell A to store a new value to this explicit cookie file. My solution is:
Server B (which is not the client who has started the session!) calls a PHP file on Server A. After B has passed some security checks A should write a new value to this cookie file with file_puts_content. Note, as written Server B has not started the session so I think I cannot simple do
session_start();
$_SESSION['myval'] = "new val";
Therefore I have following questions:
Is there an easier (native session handling) way instead of file_puts… to write the value to the cookie file something like:
write $_SESSION['myval'] = "new val" to
sess_489b9515146e7390ac03b5dabf36b70e
The session Dir var/lib/php5 has chmod 773, to write and search within it I have to change rights to 777 (urrgh). How can I keep 773 but make it useable for php
If I open a cookie file a value looks like this: place|s:6:"Muster"; What does |s:6: mean?
Kind regards,
tony
You should use a DB like MySQL to store your sessions, then abstract all session calls into that database.
see 1.
This is how PHP types are serialized to a string. In this case s:6:"Muster" is a string 6 chars long, which happens to be "Muster".

Passing values between PHP scripts in this particular situation

So in my HTML markup I have an image tag like this one:
<img src="image_generation.php" alt="template" id="image" />
And the 'src' attribute links to a PHP script that generates an image using a couple of variables defined there which are mostly randomly generated.
Now, what I want to be able to do is to access those random variables in the page which includes the image generation script. I suppose I could send cookies and access them after the image tag as they technically should be readily available to the including file. I don't want to send too much information, just a couple (10-20) variables. Not sure if in that case sessions would be a better choice, as I would have to send several cookies. Sessions also pose a problem as the including script gets the old session and I would have to refresh the page to obtain the values of the previously generated image. I suppose I could also set up a DB and access the DB in the including script, but the variables are temporary and I would have to delete them and that seems like a lot of fuss to me.
The image generation script finishes with:
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);
And nothing can be sent to the browser before the header call or else the image won't be displayed. If I use cookies or sessions, the image_generation.php would have to send both the image and set the cookie(s)/session.
None of the options (cookies, sessions or DB) really convince me, as there are problems with each in this particular situation. Can you think of a way to solve this? Thanks.
MAJOR EDIT #1:
Including script gets session of previously generated image without refreshing / Setting cookie(s) and/or a session in included script before / after sending image without output buffering does not pose a problem.
You can use a $_SESSION, but to make the session available in the same script that included the <img> tag (which would have executed before the image script), you would need to make AJAX calls via JavaScript. An AJAX handler that runs at window.onload should have access to the $_SESSION created by the image script, since the image should have fully loaded when it executes.
Example PHP handler getsession.php:
header('Content-type: application/json');
// Simply part of the session into JSON
// Obviously you would want to limit this to only the variables
// that should be sent back, so you don't expose the session on the client side!
echo json_encode(array($_SESSION['var1'],$_SESSION['var2']));
exit();
Example AJAX call (using jQuery since it will be easy to get started with)
// Variable to hold the object returned by PHP
var imgPHPSession;
$(window).load(function() {
$.ajax({
url: 'getsession.php',
dataType: 'json',
success: function(data) {
imgPHPSession = data;
}
});
});
Update:
It can be done entirely in PHP, but would require changing your design a bit such that the variables necessary to generate the image are created in $_SESSION by the main script. They are then available in $_SESSION to image_generation.php to be used as needed, but are already known to the main script.
Update 2:
Since the image vars contain info about how it was created, if the image is not too large, you can actually create it in the main script and store it to disk. The image_generation.php script can still be used as the <img src>, but its purpose would then be to retrieve the correct image from disk and serve it back to the browser and delete it from disk when no longer needed. The $_SESSION is then available to both the main and image scripts.
You can pass you parameters to src attribute, for example:
<img src="image_generation.php/user/1/name/tom/param1/variable2"
or
<img src="image_generation.php?user=1&name=tom
this solution lets you forget about session, cookies - it's stateless
Php can do smart tricks with buffer by ob_* function, so at the beginning of your script you can call ob_start() to buffer every php output, it lets you avoid all 'Header already send' errors.
Your image_generation.php does not need to send any cookie. This script will receive cookie with sessionid (browser attach cookie information to every request to the server) what makes possible identify user session on php side - after that you have access to every session parameters.

CMS Made Simple: Session getting reset between page views

I have a form in a template which is posted to a PHP script. This script sets some variables in the $_SESSION array, then redirects back to the same page using the standard:
header("Location: index.php?page=enquiry-form");
The problem is that whenever the page loads after refirection, the session only contains the following three variables:
cmsuserkey
cms_admin_user_id
cms_admin_username
...all of mine have disappeared.
I'm calling session_start(); in my php script
I've set the config option: $config['use_smarty_php_tags'] = true;
The user doesn't need to be logged in to use the form (in fact the site doesn't use logins at all).
Can anyone suggest anything I'm not doing/doing wrong?
Thanks,
Rich
I had the same problem once and fixed it by addin exit() after the redirection to save the session:
header("Location: index.php?page=enquiry-form");
exit();
I've had a similar problem (though I wanted to use data from the CMS Made Simple session in another php-file). For me the cause was the following (as stated in my comment on the question):
CMS Made Simple (CMS from now on) does makes its own session name. This means that when you run session_start() in a separate php-file, it will not have the same session name. Therefore, the php-file won't be able to access CMS's session data, and CMS won't be able to access the php-file's session data.
The solution logically follows from the cause, you need them both to use the same session name.
CMS sets its session name in include.php which should be in the app's root folder.
$dirname = dirname(__FILE__);
...
$session_key = substr(md5($dirname), 0, 8);
#Setup session with different id and start it
#session_name('CMSSESSID' . $session_key);
So, in your php file you will need to do the following (before calling session_start();):
//Substitute the string $dirname for the result of __FILE__ in **include.php**!!!
$dirname = '/data/web/somefolder/someotherfolder/'
$session_key = substr(md5($dirname), 0, 8);
#session_name('CMSSESSID' . $session_key);
//Now you can call session_start();
Doing this lets your php-file access CMS's Session. If you use any plugins that put essential data in the session, you'll want to be careful not to erase any of that data.
NOTE: I use CMS version 1.8.2, this solution may not work if you use a different version.

Create temporary file and auto removed

I am writing a anti-leeching download script, and my plan is to create a temporary file, which is named by session ID, then after the session expires, the file will be automatically deleted. Is it possible ? And can you give me some tips how to do that in PHP ?
Thanks so much for any reply
PHP has a function for that name tmpfile. It creates a temporary file and returns a resource. The resource can be used like any other resource.
E.g. the example from the manual:
<?php
$temp = tmpfile();
fwrite($temp, "writing to tempfile");
fseek($temp, 0);
echo fread($temp, 1024);
fclose($temp); // this removes the file
?>
The file is automatically removed when closed (using fclose()), or when the script ends. You can use any file functions on the resource. You can find these here. Hope this will help you?
Another solution would be to create the file in the regular way and use a cronjob to regular check if a session is expired. The expiration date and other session data could be stored in a database. Use the script to query that data and determine if a session is expired. If so, remove it physically from the disk. Make sure to run the script once an hour or so (depending on your timeout).
So we have one or more files available for download. Creating a temporary file for each download requests is not a good idea. Creating a symlink() for each file instead is a much better idea. This will save loads of disk space and keep down the server load.
Naming the symlink after the user's session is a decent idea. A better idea is to generate a random symlink name & associate with the session, so the script can handle multiple downloads per session. You can use session_set_save_handler() (link) and register a custom read function that checks for expired sessions and removes symlinks when the session has expired.
Could you explain your problem a bit more deeply? Because I don't see a reason why not to use $_SESSION. The data in $_SESSION is stored server-side in a file (see http://php.net/session.save-path) BTW. At least by default. ;-)
Ok, so we have the following requirements so far
Let the user download in his/her session only
no copy & paste the link to somebody else
Users have to download from the site, e.g. no hotlinking
Control speed
Let's see. This is not working code, but it should work along these lines:
<?php // download.php
session_start(); // start or resume a session
// always sanitize user input
$fileId = filter_input(INPUT_GET, 'fileId', FILTER_SANITIZE_NUMBER_INT);
$token = filter_input(INPUT_GET, 'token', FILTER_UNSAFE_RAW);
$referer = filter_input(INPUT_SERVER, 'HTTP_REFERER', FILTER_SANITIZE_URL);
$script = filter_input(INPUT_SERVER, 'SCRIPT_NAME', FILTER_SANITIZE_URL);
// mush session_id and fileId into an access token
$secret = 'i can haz salt?';
$expectedToken = md5($secret . session_id() . $fileId);
// check if request came from download.php and has the valid access token
if(($expectedToken === $token) && ($referer === $script)) {
$file = realpath('path/to/files/' . $fileId . '.zip');
if(is_readable($file)) {
session_destroy(); // optional
header(/* stuff */);
fpassthru($file);
exit;
}
}
// if no file was sent, send the page with the download link.
?>
<html ...
<?php printf('a href="/download.php?fileId=%s&token=%s',
$fileId, $expectedToken); ?>
...
</html>
And that's it. No database required. This should cover requirements 1-3. You cannot control speed with PHP, but if you dont destroy the session after sending a file you could write a counter to the session and limit the number of files the user will be sent during a session.
I wholeheartedly agree that this could be solved much more elegantly than with this monkeyform hack, but as proof-of-concept, it should be sufficient.
I'd suggest you not to copy the file in the first place. I'd do the following: when user requests the file, you generate a random unique string to give him the link this way: dl.php?k=hd8DcjCjdCkk123 then put this string to a database, storing his IP address, maybe session and the time you've generated the link. Then another user request that file, make sure all the stuff (hash, ip and so on) matches and the link is not expired (e.g. not more that N hours have passed since the generation) and if everything is OK, use PHP to pipe the file. Set a cron job to look through the DB and remove the expired entries. What do you think?
tmpfile
Creates a temporary file with a unique
name in read-write (w+) mode and
returns a file handle. The file is
automatically removed when closed
(using fclose()), or when the script
ends.
Maybe it's to late for answering but I'm try to share on feature googlize!
if you use CPanel there is a short and quick way for blocking external
request on your hosted files which name is: HotLink.
you can Enable HotLinks on you Cpanel and be sure nobody can has request o your file from another hosting or use your files as a download reference.
To acheive this, I would make one file and protect it using chmod - making it unavailable to the public. Or, alternatively, save the contents in a database table row, fetch it whenever required.
Making it downloadable as a file. To do so, I would get the contents from the protected file, or if it is stored in a database table, fetch it and simply output it. Using php headers, I would, give it a desired name, extension, specify it's type, and finally force the browser to download the output as a solid file.
This way, you only need to save data in one place either, in a protected file or in database. Force client browser to download it as many times as the the conditions meet e.g., as long as the user is logged-in and so on. Without having to worry about the disk space, making any temp file, cronJobs and or auto-deletion of the file.

PHP Session data not being saved

I have one of those "I swear I didn't touch the server" situations. I honestly didn't touch any of the php scripts. The problem I am having is that php data is not being saved across different pages or page refreshes. I know a new session is being created correctly because I can set a session variable (e.g. $_SESSION['foo'] = "foo" and print it back out on the same page just fine. But when I try to use that same variable on another page it is not set! Is there any php functions or information I can use on my hosts server to see what is going on?
Here is an example script that does not work on my hosts' server as of right now:
<?php
session_start();
if(isset($_SESSION['views']))
$_SESSION['views'] = $_SESSION['views']+ 1;
else
$_SESSION['views'] = 1;
echo "views = ". $_SESSION['views'];
echo '<p>Refresh</p>';
?>
The 'views' variable never gets incremented after doing a page refresh. I'm thinking this is a problem on their side, but I wanted to make sure I'm not a complete idiot first.
Here is the phpinfo() for my hosts' server (PHP Version 4.4.7):
Thanks for all the helpful info. It turns out that my host changed servers and started using a different session save path other than /var/php_sessions which didn't exist anymore. A solution would have been to declare ini_set(' session.save_path','SOME WRITABLE PATH'); in all my script files but that would have been a pain. I talked with the host and they explicitly set the session path to a real path that did exist. Hope this helps anyone having session path troubles.
Check to make sure you are not mixing https:// with http://. Session variables do not flow between secure and insecure sessions.
Had same problem - what happened to me is our server admin changed the session.cookie_secure boolean to On, which means that cookies will only be sent over a secure connection. Since the cookie was not being found, php was creating a new session every time, thus session variables were not being seen.
Use phpinfo() and check the session.* settings.
Maybe the information is stored in cookies and your browser does not accept cookies, something like that.
Check that first and come back with the results.
You can also do a print_r($_SESSION); to have a dump of this variable and see the content....
Regarding your phpinfo(), is the session.save_path a valid one? Does your web server have write access to this directory?
Hope this helps.
I had following problem
index.php
<?
session_start();
$_SESSION['a'] = 123;
header('location:index2.php');
?>
index2.php
<?
session_start();
echo $_SESSION['a'];
?>
The variable $_SESSION['a'] was not set correctly. Then I have changed the index.php acordingly
<?
session_start();
$_SESSION['a'] = 123;
session_write_close();
header('location:index2.php');
?>
I dont know what this internally means, I just explain it to myself that the session variable change was not quick enough :)
Check to see if the session save path is writable by the web server.
Make sure you have cookies turned on.. (I forget when I turn them off to test something)
Use firefox with the firebug extension to see if the cookie is being set and transmitted back.
And on a unrelated note, start looking at php5, because php 4.4.9 is the last of the php4 series.
Check who the group and owner are of the folder where the script runs. If the group id or user id are wrong, for example, set to root, it will cause sessions to not be saved properly.
Check the value of "views" when before you increment it. If, for some bizarre reason, it's getting set to a string, then when you add 1 to it, it'll always return 1.
if (isset($_SESSION['views'])) {
if (!is_numeric($_SESSION['views'])) {
echo "CRAP!";
}
++$_SESSION['views'];
} else {
$_SESSION['views'] = 1;
}
Well, we can eliminate code error because I tested the code on my own server (PHP 5).
Here's what to check for:
Are you calling session_unset() or session_destroy() anywhere? These functions will delete the session data immediately. If I put these at the end of my script, it begins behaving exactly like you describe.
Does it act the same in all browsers? If it works on one browser and not another, you may have a configuration problem on the nonfunctioning browser (i.e. you turned off cookies and forgot to turn them on, or are blocking cookies by mistake).
Is the session folder writable? You can't test this with is_writable(), so you'll need to go to the folder (from phpinfo() it looks like /var/php_sessions) and make sure sessions are actually getting created.
If you set a session in php5, then try to read it on a php4 page, it might not look in the correct place! Make the pages the same php version or set the session_path.
I spent ages looking for the answer for a similar problem. It wasn't an issue with the code or the setup, as a very similar code worked perfectly in another .php on the same server. Turned out the problem was caused by a very large amount of data being saved into the session in this page. In one place we had a line like this:$_SESSION['full_list'] = $full_list where $full_list was an array of data loaded from the database; each row was an array of about 150 elements. When the code was initially written a couple of years ago, the DB only contained about 1000 rows, so the $full_list contained about 100 elements, each being an array of about 20 elements. With time, the 20 elements turned into 150 and 1000 rows turned into 17000, so the code was storing close to 64 meg of data into the session. Apparently, with this amount of data being stored, it refused to store anything else. Once we changed the code to deal with data locally without saving it into the session, everything worked perfectly.
I know one solution I found (OSX with Apache 1 and just switched to PHP5) when I had a similar problem was that unsetting 1 specific key (ie unset($_SESSION['key']);) was causing it not to save. As soon as I didn't unset that key any more it saved. I have never seen this again, except on that server on another site, but then it was a different variable. Neither were anything special.
Thanks for this one Darryl. This helped me out. I was deleting a session variable, and for some reason it was keeping the session from committing. now i'm just setting it to null instead (which is fine for my app), and it works.
I know one solution I found (OSX with Apache 1 and just switched to PHP5) when I had a similar problem was that unsetting 1 specific key (ie unset($_SESSION['key']);) was causing it not to save. As soon as I didn't unset that key any more it saved. I have never seen this again, except on that server on another site, but then it was a different variable. Neither were anything special.
Here is one common problem I haven't seen addressed in the other comments: is your host running a cache of some sort? If they are automatically caching results in some fashion you would get this sort of behavior.
Just wanted to add a little note that this can also occur if you accidentally miss the session_start() statement on your pages.
Check if you are using session_write_close(); anywhere, I was using this right after another session and then trying to write to the session again and it wasn't working.. so just comment that sh*t out
I had session cookie path set to "//" instead of "/". Firebug is awesome.
Hope it helps somebody.
I had this problem when using secure pages where I was coming from www.domain.com/auth.php that redirected to domain.com/destpage.php. I removed the www from the auth.php link and it worked. This threw me because everything worked otherwise; the session was not set when I arrived at the destination though.
A common issue often overlooked is also that there must be NO other code or extra spacing before the session_start() command.
I've had this issue before where I had a blank line before session_start() which caused it not to work properly.
Adding my solution:
Check if you access the correct domain. I was using www.mysite.com to start the session, and tried to receive it from mysite.com (without the www).
I have solved this by adding a htaccess rewrite of all domains to www to be on the safe side/site.
Also check if you use http or https.
Edit your php.ini.
I think the value of session.gc_probability is 1, so set it to 0.
session.gc_probability=0
Another few things I had to do (I had same problem: no sesson retention after PHP upgrade to 5.4). You many not need these, depending on what your server's php.ini contains (check phpinfio());
session.use_trans_sid=0 ; Do not add session id to URI (osc does this)
session.use_cookies=0; ; ensure cookies are not used
session.use_only_cookies=0 ; ensure sessions are OK to use IMPORTANT
session.save_path=~/tmp/osc; ; Set to same as admin setting
session.auto_start = off; Tell PHP not to start sessions, osc code will do this
Basically, your php.ini should be set to no cookies, and session parameters must be consistent with what osc wants.
You may also need to change a few session code snippets in application_top.php - creating objects where none exist in the tep_session_is_registered(...) calls (e eg. navigation object), set $HTTP_ variables to the newer $_SERVER ones and a few other isset tests for empty objects (google for info). I ended up being able to use the original sessions.php files (includes/classes and includes/functions) with a slightly modified application_top.php to get things going again. The php.ini settings were the main problem, but this of course depends on what your server company has installed as the defaults.

Categories