I've used session vars multiple times in the past, with no problems, but now it's got me...
The $_SESSION var I am setting is becoming unset every time the PHP script is fired, although it is setting ok for one variable at a time.
if (!isset($_SESSION['badList'])) {
print 'not set - again?';
$_SESSION['badList'][0] = $lineNum;
}
else
{
$_SESSION['badList'][count($_SESSION)] = $lineNum;
}
Here 'not set - again?' fires every time I perform the suitable action, i.e. PHP is not able to find the initial session var. The session cache seems to clear completely when a script is run, which sort of ruins the point of sessions.
What can I do? Many thanks.
Ensure you've called session_start(), /etc/php.ini (or system equivalent) has a session.save_path set (ususally /var/lib/php/session/) and that directory is writable by your web server (on Linux it should be drwxrwx---) and that your disk is not full. If your sessions are being written to a remote store (database, memcached etc) make sure you can connect to that with the credentials your app uses (if applicable).
edit: also ensure you are calling session_write_close() at the end of your request - if you don't then the session data may not be written
Related
I thought about some helper to manage session variables on my development localhost.
I would like to read,change and delete session variables from ALL vhosts on my machine.
As far i know, from PHP i can access only current host session variables, which will be populated to $_SESSION variable, after call to session_start. That's not enough for my needs.
After some research (ex. Access active sessions in PHP) i found solution :
Load all files from php session directory
Use session_decode to load data to $_SESSION variable
Read/change/delete some variables
Use session_encode to encode my session back to file
There is any better method to do that?
Maybe there is already dedicated tool for that task?
EDIT:
Another solution which i now currenty use is just enable debugger in IDE for desired project, and use watches/stack window to edit session.
EDIT2:
I dont want any project-specific solution like storing session data in database. This should work "out-of-the-box", for any project.
For better understanding, use example:
In magento admin panel grid filters are stored in session variables.
When you enable broken filter there is an error page, and you can't easily disable this filter without removing session cookie, or setting debugger for it.
I spend some time once with a script that programatically "expires" server sessions to obtain info about user inactivity. On that occasion, I had a database with session_ids to transverse, but it can be done with directory listing (note that are php's compilation specific advices on code)
//Preserve runtime variable
$pre_config = ini_get('session.use_cookies');
//Check previous session_start();
if($previous_sid = session_id()){
//close and save current session
session_write_close();
}
//To determine where php session files are stored, see http://stackoverflow.com/questions/4927850/location-for-session-files-in-apache-php
if(($save_path = session_save_path()) === ''){
// PHP compilation specific
// There are diferences between CLI (saves in sys_get_temp_dir()) and mod_php (where session_save_path() works) on Fedora 12
$save_path = '/var/lib/php/session/';
session_save_path('/var/lib/php/session/');
}
//Avoid new cookies from other session_start()
ini_set('session.use_cookies', false);
//Do the magic
if ($handle = opendir($save_path)) {
while (false !== ($entry = readdir($handle))) {
if (strpos($entry, 'sess_') === 0) {
$session_id = str_replace('sess_' , '', $entry);
session_id($session_id);
session_start();
//Do whatever you want with this session, using $_SESSION
session_write_close();
}
}
closedir($handle);
}
//Restore previous configuration
ini_set('session.use_cookies', $pre_config);
//Restore previous session
if($previous_sid) {
session_id($previous_sid);
session_start();
}
I do not recommend running this code on client request. Remember that session_start block script execution while "session id" is in use on another request. And I think that is not recommended to run it by a CLI script, because PHP embedded on WebServers and PHP CLI uses different environment and configurations (besides the fact that the running user of a PHP CLI must be the same user that runs the WebServer to prevent permission deny).
I think that the ideal solution is to trigger requests to this script with a HTTP GET periodically (by linux crontab or similar), of course this solution depends on final use been planned. If HTTP request trigger can be done, the part of the code that saves previous settings and session can be eliminated.
Due to server settings I am having to use $_COOKIE instead of $_SESSION to manage session vars for a project.
On my search form I set an initial cookie but am unclear whether this is helpful or needed?
setcookie('NOSG', 'oHai', time()+7200, '/', 'some.org');
Each time the search results page loads I iterate over the cookies and back date the ones I need to clear and then set the new values like so:
if ($board) {
foreach ($_COOKIE as $k => $v) {
if (preg_match('/boa_/', $k)) {
setcookie($k, '', time()-3600, '/', 'some.org');
}
}
foreach ($people as $p) {
setcookie('boa_'.$p->ID, $p->whatever, time()+7200, '/', 'some.org');
}
}
Mostly this is used for making sticky selections in multi-line <SELECT> inputs.
Is this approach sound? I have rarely used $_COOKIE for anything.
// EDIT 1:12 PM GMT-06:00
All of the comments and answers are focused on fixing sessions. I assume this is because there is some reason the method suggested is NOT sound? The question asked is about using $_COOKIE to remember form settings. Would anyone care to respond as to why the method I am using is or is not appropriate to the problem?
The error
Permission denied. session.save_path is set to /var/lib/php/session PHP Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/var/lib/php/session) in Unknown on line 0
Is due to an error on the part of your host/system administrator. They should set the permissions on /var/lib/php/session to 777 so it is writable by all users. If they are using something that executes your PHP script as your user, the data is still safe because your user will own the session data file so no one else can view or modify it.
Alternatively, you can change the session save path on the fly to a directory under your control.
If you were to have a common file that initiated your session, add this before session_start():
session_save_path('/home/yoursite/sessions');
// or
session_save_path($_SERVER['DOCUMENT_ROOT'] . '../sessions');
// or, an alternate method
ini_set('session.save_path', '/home/yoursite/sessions');
session_start();
Then just created that folder and set the permissions appropriately so it is readable/writable by your user only.
Technically all a session is, is a text file (OK, you can hold the data in a database as well) containing variables that's identified by a value held in a cookie (or the address bar).
It wouldn't be impossible to recreate the functionality within PHP using things like setcookie(), serialize() and file_put_contents() writing to a folder outside the web tree ... though you might also need a Cron job to schedule garbage collection (to be fair, PHPs native session GC doesn't seem to be spectacular).
You'd just need to create a custom session handling object and set the "session" id for it in a cookie exactly the same as if you were using normal session handling - except instead of using $_SESSION you'd use you Session::get() and Session::set() methods.
If you keep the API clean then, at a future date if you manage to get session handling enabled on the server, you'd only need to tweak your session handling object and it wouldn't affect the rest of your program code - it's probably a good idea to abstract away then session handling anyway.
None of the respondents addressed my question: Is using $_COOKIE to store session data a sound method?
Experience has taught me what they would not. Not all browsers handle cookies in the same way. For instance Internet Explorer has limits per domain on the number of cookies: http://support.microsoft.com/kb/941495
So the answer is- $_SESSION is superior to cookies as it is handled by PHP in the same manner for all browsers.
I was working in a project where another developer wrote the code,while a user is login the session_start() as usual and then he is cheking like belows:
if($a['userName'] == $username && $a['password'] == $pwd)
{
$_SESSION['id'] = $a['id']; ?> <script language="javascript"type="text/javascript">window.location="host.php";</script> } else {
$msg= "Invalid Username Password";
}
And when a user want to use the form after couple of seconds its logout and user can not submit data.
I have tried increasing session life time duration:
$sessionCookieExpireTime=8*60*60;
session_set_cookie_params($sessionCookieExpireTime);
And also tried with increasing session lifetime in runtime like below:
ini_set('session.gc_maxlifetime', '3600');
And finally tried by increasing php.ini session lifetime .
Unfortunately those did not work.
One thing I should mention that,there is no session_destroy() for logout issues.
Thanks in advance.
What kind of server are you working on?
On a shared server that runs multiple sites that use a shared session directory the session.gc_maxlifetime is in effect the shortest lifetime of all sites accessing that shared directory.
If the problem is on a development server, find out where the session files are stored and look at what happens to them.
It is also possible that the directory where the sessions are stored is not writeable. In that case the session variable is never stored in the first place.
In all three cases: try to store the session files in a different directory. In code you have to set the session directory with session_save_path() before you call session_start().
The timeout occurs when user idle activity for certain time. There is no way to logout automatically unless using session_destroy.
It may be possible that your code
$a['id'];
returns null by chance.
Also, you need to checkout which page is getting logged out.
Giving the full code may be easy to identify the issue.
I am creating an upload feature that stores a user uploaded file on the server with the user's session-id as its name. Now, I want to keep this file on the server only till that session is active.
So, my question is, how can I determine from the session-id, whether a session is active or expired so that in the later case I can safely delete the user uploaded file.
This I want to do as a cleanup at particular intervals maybe by using a cron job, though I have never used it before.
You can't just rely on session.gc_maxlifetime because after this time the session is marked as garbage and the garbage collector starts only with a probability of 1% by default ( session.gc_probability).
The better approach IMHO is to handle yourserlf the expired data.
You can for instance start the time and save it into a session variable:
<?php $_SESSION['last_seen'] = time();//Update this value on each user interaction. ?>
Later..via cron you can do something like this:
<?php
//Get the session id from file name and store it into the $sid variable;
session_id($sid);//try to resume the old session
session_start();
if (isset($_SESSION['last_seen']) && $_SESSION['last_seen'] > $timeout){//Session is expired
//delete file
session_destroy();
}else if (!isset($_SESSION['last_seen')){ //already garbaged
//delete file
session_destroy();
}
?>
Not tested...just an idea
I'm trying to do the exact same thing. One solution would be to define a custom garbage collector function with session_set_save_handler(). In this custom function you would delete the uploaded files associated with the session and then delete the session from disk. The only problem I see it's that you will have to define the rest of the session handlers as well:
bool session_set_save_handler ( callback $open,
callback $close,
callback $read,
callback $write,
callback $destroy,
callback $gc )
This is easy if you don't rely on PHP to handle sessions. Is there a way to call the default handler functions of PHP from a custom handler function?
Intervals can be made like this - someone opens your web -> php script is running -> it checks if files is time-outed -> delete time-oted files
And no CRON needed :-)
It is nearly impossible to determinate due to lack of information if user closed or not the browser window ( if he don't closes it but turn sleep mode on and come back in 2 days - session is still active AFAIK ) -
only idea to slove this problem in best manner this is to use own session engine with AJAX checking.
I have always wondered, if a PHP session times out during the middle of executing a script, will the contents of the $_SESSION array still be available until script execution ends? For example:
session_start();
if(! isset($_SESSION['name'])) {
echo 'Name is not set';
exit;
}
// imagine there is a bunch of code here and that the session times out while
// this code is being executed
echo 'Name is ', $_SESSION['name']; // will this line throw an error?
Is it practical to copy session variables to the local scope so I can read them later on in the script without having to keep checking for a session time out? Something like:
session_start();
if(isset($_SESSION['name'])) {
$name = $_SESSION['name'];
} else {
echo 'Name is not set';
exit;
}
// bunch of code here
echo 'Name is ', $name;
don't worry about such things. Nothing will happen to the session. It's initialised by sessioni_start() and $_SESSION will be always available within your script.
The default three-hour session lifetime is reset each time you open the session (see session_cache_expire), so the only way a session could time out in the middle of a request is if a request takes three hours to process. By default PHP requests time out after just 30 seconds, so there's no danger of session expiry during a request. Furthermore, the $_SESSION variable won't suddenly change in the middle of a request. It's populated when the session starts, and that's it.
The variables are copied into the $_SESSION global at the initial request, so it has the same effect as copying it to a local variable.
However, for clarity sake, it makes sense to copy it to a local variable. Especially if you plan to use the variable several times. It can be difficult to read code that has $_SESSION['variable'] all over the place.
What you needed to understand is how sessions work. A client accessing a script using a $_SESSION super global only knows the key to the session that belongs to them (Stored in Cookie/URL). This means the session data itself has nothing to do with the client. If you have the key to the session data you want to use then you can use it. Older versions of PHP had some security holes because sessions where stored somewhere that was easily accessible (I don't remember details).
Basically, if you have the session id in a PHP script you have access to that session unless the memory on the machine is flushed/harddrive is corrupt (ie Computer Restart/Device Failure).
Hope this helps, otherwise go to php.net and dive into the details on how sessions work.