$_SESSION superglobal is being emptied unexpectedly - php

I am using sessions in an attempt to implement persistent logins for my users in a web application. The back-end is php 7.2 and apache, provided through Namecheap shared hosting.
I am setting a session cookie on the client with a "cookie_lifetime" and "gc_maxlifetime" of 604,800 seconds (one week). The server calls session_start() with these parameters and checks a $_SESSION key called "user_id" to see if the session_start() call has started an existing session (if the key is defined, the user is "logged in"). It does this every time the page is loaded. Everything works fine until about 40 minutes of inactivity have gone by, then the next page refresh and attempt to call session_start() and access any $_SESSION keys returns undefined for everything, despite the session cookie still showing an "Expires" value several days in the future in DevTools.
My understanding was that "cookie_lifetime", "gc_maxlifetime", and the associated "Expires" header for setting the client-side cookie would preserve session information for at least as long as the time specified, but this interaction is demonstrating that regardless of what I put in those fields, the $_SESSION superglobal will not return anything meaningful beyond ~40 minutes of inactivity.
Am I not understanding this correctly, or is there perhaps something wrong from a server configuration standpoint that is beyond the scope of the client-server application code?

I didn't fully get to the bottom of why this was occurring. I did reach out to the Namecheap support staff, however, and they told me their sessions were not malfunctioning in the same way after ~40 minutes; they continued to see session values that had been set several hours previously when they tried to recreate the issue using the same code and configuration as I was using.
I dug into the server configuration and reviewed the output of a phpinfo() dump and determined that the Registered save handlers were set to files user. I can't find out what the user component of that reflects, and maybe that's where the issue lies, but I was able to resolve the issue by explicitly specifying the session.save_path parameter rather than relying on the default (which was no value in the phpinfo output).
The support staff had said that the default location was /home/[user]/tmp/ and their sessions were showing up there, but mine were not. After adding the explicit save_path to php.ini, my sessions began to appear there and the ~40 minute expiration stopped occurring.
I'll hold off on accepting this as the answer in case anyone else can provide more insight/understanding, but I wanted to at least chime in saying that I had found a solution to my problem. I'm not sure what was happening before, but I could not find my session files anywhere sensible in the directories of my shared host user account and I'm wondering if they were there at all. It's also very strange to me that it worked for the support staff but not for me or a friend that I had test it on his own computer.

Related

CodeIgniter Random Logout (sess_time_to_update = PHP_INT_MAX)

I have one user reporting that they are being logged out at 6:45 pm est (around that time). My session expire time is 24 hours and they login about 8 hours earlier.
Just as a test I set sess_time_to_update to PHP_INT_MAX as their is a known bug that causes session logouts when it is rotating the session.
The only thing I can think of that would cause this is Firefox's ability to restore previous tabs. This actually restores the session cookie even after the browser is closed.
She said this also happens in Internet Explorer...I couldn't find a setting in IE 11 to persist session cookies after the browser closes.
Do you have any ideas what could be causing this or an idea of what to investigate?
EDIT: This happened to another client. It happens only some days and doesn't happen to users at a different location. Is there anything I can do to determine how this is happening?
Try testing it in a few different browsers and see if it's still happening.
If it is, maybe:
Check if there are any cron jobs running server side that could be killing session cookies on the server?
Use a tool like IECookiesView to see what cookies are there, when they're set to expire and if anything is changing?
If they keep getting logged out at similar times try working out anything that might be happening server or local side at that time. It's unlikely a restore tabs (with cookies) feature could be randomly running at the same time.
I remember seeing a feature in Firefox to clear all cookies on exit as well, are they rebooting around that time?
Hope I helped.
I'm not sure that you're setting the actual expiration period of sessions to PHP_INT_MAX. As stated in the manual sess_time_to_update config controls how often the session class will regenerate itself and create a new session ID. In other words it's how often the session details (such as last activity) are getting updated, not expired.
On the other hand there are a few configuration directives that have influence on unexpected session expirations of your case:
sess_expiration: The number of seconds you would like the session to last. The default value is 2 hours (7200 seconds). If you would like a non-expiring session set the value to zero: 0.
sess_expire_on_close: Whether to cause the session to expire automatically when the browser window is closed.
Make sure that these settings are set fine and then try to reproduce the situation on your own browser to minify the scope of the problem. If you still experience random logouts add a log_message() call to session library's sess_destroy() to keep track of user session destruction that may give you a clue about the destruction pattern.
If nothing, I think that would be user's browser or CCleaner-like apps on her machine wiping off the cookie. Instruct her to factory reset her browser settings or install a brand new browser.
The other thing worth noting is that some CI libraries such as IonAuth has their own related configs. If you're using IonAuth for authentication please have a look at user_expire and remember_users directives in the ion_auth.php config file.
Hope it helps.

PHPSESSID changes in every request ONLY under one internet connection

After one day of extensive research on the internet, I still can't figure out this one.
What is happening is that PHPSESSID in the cookie isn't persisting from one page to another.
This is happening in computers under one internet connection in a specific place. I've tested several others machines located elsewhere and everything works fine. I've checked session_start, there's no problem with subdomains.
I hope someone can help me out.
Things to check:
Is the time (and time zone!) set correctly on those computers? If it's set incorrectly, they may be discarding session cookies prematurely (possibly even immediately).
Is any odd security or "privacy" software installed on the computers? If possible, check if the issue persists under another browser on those machines.
Are these computers behind any sort of web proxy? If so, it may be meddling with cookies.
To use cookie-based sessions, session_start() must be called before
outputing anything to the browser. - PHP Documentation
Also you may want to check that your php.ini is configured properly to store your session cookies. Either that or call session_set_cookie_params() every time the page is loaded before the session is started in order to properly configure the session cookie's folder, domain, duration, etc.
Set cookie parameters defined in the php.ini file. The effect of this
function only lasts for the duration of the script. Thus, you need to
call session_set_cookie_params() for every request and before
session_start() is called.
This function updates the runtime ini values of the corresponding PHP
ini configuration keys which can be retrieved with the ini_get().
After I verified with my own computer that this was happening in this place, I realised that when I typed some URLs, they got somehow changed in the middle, for example http://www.medicmanager.com.ar/cloud/santiago/charisma/js/jquery.cookie.js was changed into http://www.medicmanager.com.ar/cloud/santiago/charisma/js/jquery.ckiooe.js, which of course gave 404.
I changed the ISP connection to another, and it started working, so I called the ISP and they told me they've been with this problem for 2 days, changing URLs and messing up with cookies.
Thank you all for your answers, and I leave this here in case someone is in doubt. Yes, it can be your ISP, very strange.
Setting the cookie lifetime to 0 means it will expire straight away, try setting it to another value e.g. 2592000 - which is 30 days in seconds.
EDIT: I meant time() + 2592000

PHP 5.3.3 - running session_start() in subdirectory kills existing session

I've been trying to track down some annoying session issues since my webhost upgrade to PHP 5.3.3 awhile back. I've determined that if there is an active session, calling session_start() from a subdirectory kills the existing session. As an example, I start a session and a user logs in to domain.com/index.php then the user navigates to domain.com/members/ which fires start_session() ... the user's session is lost.
I've dug around for this and can't find anything similar. Is there a PHP configuration that would account for this behavior?
Calling session_start() multiple times with that version of PHP shouldn't cause any problems, however there are other possible causes.
One possible explanation is that the client's browser isn't sending the session id back to the server. You can test this out by comparing the session id that both pages produce. Assuming that you have a controlled environment where you can test this properly, you can use session_id() to get the session.
It might also be that the user is hitting a different webserver. Since (by default) PHP stores sessions to disk, there is no way for multiple servers to share the session information. If this is a shared host, it's probably quite unlikely this is the cause. You can test this out however by using phpinfo(). It should give you enough information to determine if it's the same server or not. For multi-server systems, I'd look at storing sessions in memcache or mysql.
if your sessions works all right within the same directory (it is unclear from your question), there is the only possible reason for such a behavior, a pretty obvious one: "directory" cookie parameter.
It seems it is set to somewhat unusual value, other than default "/" for the session cookie parameter.
You have to check it out.
Anyway, it is almost useless to try ANY session/cookie related problem without an HTTP interchange log.
You have to use some HTTP sniffer, like LiveHTTPHeaders Firefox addon to see what cookie header was sent by the server and which one was returned by client.
Otherwise it's all going to be shooting in the dark.
Okay, as it seems from your yonder comment, the session id remains the same, so, no HTTP issue can be a reason. The issue become a kinda tricky to spot.
Could you please post your test script here?
I've spent quite a long time searching, trying, testing for what looked like the same problem. As google kept sending me here, I think sharing the solution might help others (though I feel strange posting on a 2011 question):
Session variables set in /bar.php were not set in /foo/foobar.php.
It realised that the issue had nothing to do with folder/subfolder when I finally found out that the link in http://www.example.com/bar.php was pointing to http://example.com/foo/foobar.php (missing www).
Correcting the URL in the html link solved the problem. Having no time to dig deeper, what I can figure out is that (in my config) Apache makes no difference and serves pages indifferently with and without www, whereas PHP doesn't share the session between what it considers being two different domains, example.com and www.example.com.
Is there a PHP configuration that would account for this behavior?
Yes, if the storage for the session data differs between those calls, the $_SESSION content will differ as well. The storage can be configured, see http://php.net/manual/en/session.configuration.php for all configuration options you have with sessions.
Next to that if PHP is unable to read the session store, you will get an empty array as well.
I can't tell you if this is the issue with your problem, but probably it's helpful.
BTW, calling session_start() and than having an empty $_SESSION is commonly a sign that a new session has been created. You can verify this if you use cookies for your sessions and you output headers_listDocs:
echo '<pre>', var_dump(headers_list());
If it contains a new cookie for the session, the session has been created with this request.
Lots of good suggestions here. Thanks everyone. I spent a good chunk of the weekend digging into this and wasn't able to directly resolve it. I ended up demonstrating to my webhost that this problem happens on two of his hosted sites and doesn't happen in a default install of PHP. To work around the problem, I ended up moving all of my login and session logic into a single class.
Wanted to share another answer, found in this SO: Session variables not accessible in subdirectory answered by clayRay.
My answer was that I had a custom "php.ini" file saved in the root directory, and moving those directives into ini_set() calls solved it. You could also shove those over to .htaccess if your host allows.

PHP sessions expiring early

I'm having problems with the PHP site I run at work where users are being logged out after a few minutes (the exact time varies, but it is frequent enough to be an issue), regardless of whether they have been actively using the site or not.
The difficulty is that I can't reproduce this problem, if I login as the same users using the same browser I don't get logged out, which suggests it is not a case of the site being completely broken. Unfortunately I don't have access to the user machines to run any traffic-sniffing software.
The things I have already checked are:
Asking users to try different browsers. This doesn't seem to solve the problem and isn't a long-term solution anyway as I can't dictate which browsers customers will use.
The server time is correct and in line with the user machines.
The user Apache runs as has permission to write to the session folder, and I can see the session files being created and their modification times being updated.
No output buffering functions are being used.
The problem is happening on a variety of pages which seem to have nothing in common (i.e. it's not that they all use AJAX, or update the database or some other reason).
Users only access their account from one machine, i.e. they don't do a bit of work on their laptop, switch to the desktop and then wonder why they've been logged out on their laptop (we don't allow multiple simultaneous logins for the same user).
The session settings in PHP are the Debian defaults, and haven't been changed in a .htaccess file or anywhere else. The main ones are:
session.cookie_lifetime 0
session.gc_divisor 100
session.gc_maxlifetime 1440
session.gc_probability 0
session.save_handler files
session.save_path /var/lib/php5
session.use_cookies On
Debian deletes sessions through a cron job instead of using PHP's garbage collector, which is why gc_probability is set to 0. The PHP version we're running is: PHP 5.2.6-1+lenny13 with Suhosin-Patch 0.9.6.2 (cli) (latest version in Lenny, we'll be upgrading to Squeeze soon but I don't think that is the cause of the problem).
We use Zend_Session to manage sessions, and an instance of Zend_Session_Namespace is created once on every page, thus automatically calling session_start(). Sessions are cleared by calling Zend_Session::destroy() on the logout page, so the only ways a user should be logged out are:
If they explicitly click the logout link (we log when this happens and it doesn't seem to be the case that browsing are pre-fetching the page and thus logging the user out).
If they leave the session inactive for more than 24 minutes, at which point Debian will probably delete their session (there's a cron job which runs every half hour deleting all sessions which have been unmodified for over 24 minutes).
If they close the browser, as their session cookie with an expiry time of 0 will be deleted.
The checks for seeing whether a user is logged in are:
They have a valid session (checked by seeing whether we can access $zsession->user_id).
There is a row in the sessions table which has a matching user ID and session ID, and this was last updated less than an hour ago. We delete this row on logout so that even if the session still exists on disk, no one can access that account without logging in.
Can anyone suggest other things I can try?
Edit: Some additional things I have tried based on comments left:
Setting session.cookie_domain: This seems to have very odd behaviour in PHP. If I do not set this variable and leave it as the default of '' (empty string), then a request for www.domain.com will produce a cookie of www.domain.com. However, if I set cookie_domain to 'www.domain.com', the domain for the cookie is '.www.domain.com' (notice leading dot, which means valid for everything below www.domain.com, e.g. subsite.www.domain.com).
Setting session.cookie_lifetime: PHP does not seem to update the expiry time on each request, so if I set cookie_lifetime to 3600 the cookie will expire one hour after the user first visits the site, even if they login and constantly use it.
Edit 2: Based on other things people have asked:
The site is hosted in a datacentre, on a separate VLAN. No one accessing the site is on the same network as the site.
There is no IP authentication used, nor is the IP address of the client used in any part of the session process (e.g. we don't attach the session to an IP address and block the user if their next request comes from a different IP).
Debian deletes sessions through a cron job instead of using PHP's garbage collector
That's very odd - and what is the code that runs in the cron job?
We delete this row on logout
I suggest you keep this for, say, 2 days after the session has expired / is deleted (but flag it as dead at the point where you currently delete it). Also, start logging the session id in your webserver logs.
In the end, the answer was to just scrap sessions and write my own very simple cookie code which differs from sessions in the following ways:
Stores a hash (bit like a session ID) in the database rather than in files.
Sets the cookie to expire in 3600 seconds from now (updated on each page) instead of 0 seconds (the latter seemed to cause problems for IE users, although I could never replicate it).
Only sends the cookie header when the user logs in or is logged in.
It's not an ideal situation as there's some reinventing the wheel going on, but my small solution seems to work where PHP sessions didn't, and having a working site is the most important thing.
I think you count change the value of
session.gc_maxlifetime
I also faced the same problem. I spent lots of time on it then i ask my web service provider and as he got the permission he changed that vale. Now it works fine.
Are there other php applications running on the same system (under different vhosts, for instance?)? Are they also saving sessions in /var/lib/php5?
If so, and one of those apps has a low session garbage-collection threshold, they will trash your app's session files.
I do a lot of ZF development, and if I'm using filesystem-based sessions, I stick them in application/data/session instead of the system default.
your session.gc_maxlifetime is set to 1440 ms which is only 1.44 seconds. shouldn't it be 1440000 ms = 24 minutes?
You could try setting session.use_only_cookies to a value of 1 and session.cookie_lifetime to a value of 1440 seconds.
is your site on different domains ? for example domain.com, www.domain.com, subdomain.domain.com ? if some pages are redirected to a different domain (www is considered a subdomain that is different) than the sessions will not work when the address changes
EDIT:
You must reproduce the problem. Ask your clients what kind of browser do they use, what action they do until they are logedout, are they viewing the same ip for the site as you do? (that is you are both in external networks or both in the same network with the site)
When you manage to find the problem, check the request/response headers when it the session works, and also when it does not work and then compare.
In the end I opted to send a Set-Cookie header on every page request, similar to what FlyBy suggested in one of the comments. The relevant code/logic now is (assuming session_start() has already been called):
$this->session_name = session_name();
$update_cookie = isset($_COOKIE[$this->session_name]); // Check if cookie already set, as PHP will send the first Set-Cookie when the session is started
$this->logged_in = $this->checkSession(); // Function which checks whether a valid (i.e. not timed-out) session row exists in the DB
if ($this->logged_in) {
$this->updateSession(); // Update the session row to the current time
if ($update_cookie) {
// Update the cookie expiry only if it existed before the login check
setcookie($this->session_name, $_COOKIE[$this->session_name], $this->time + 3600, '/');
}
}
I'm not sure why this worked, but I haven't had any further complaints and the number of logins has dropped drastically (no longer are there several logins in the logs for the same user within a few minutes of each other).
However, I will probably rewrite the code at some point to just use a database row and a cookie on the client, because the session functionality in PHP has so many variables that it's extremely difficult to work out what is causing the problem, and the session cookie handling is slightly different to how normal cookies are handled. In particular, you have to be careful with the setcookie function, because the default path for session cookies started by PHP is '/', but the default for setcookie is the current directory path, and these will not necessarily be the same.

Session 'disappearing' on some machines

I'm not exactly sure the question I should be asking. Sorry!
I'm working on re-doing my web site so as to be using PHP5. The server lives in a buddy's basement and I just ssh in to do my coding and view the pages just like any other page out there.
I keep track of login details in $_SESSION.
When I'm sitting at my home machine I can log into the site and everything is as I expect it in terms of the SESSION being available on all pages. When I log in on my work machine, I get a successful log in and can see the SESSION variables, but as soon as I go to another page the SESSION is gone as evidenced in session_id().
My previous web site built in PHP4 (and tweaked to keep PHP5 happy) does not exhibit this behavior allowing me to log in as expected at either location before and after the change to PHP5.
I guess I'm just looking for a clue as to what to explore next... Of all the puzzles I've encountered while teaching my self to code this one appears on the face, just crazy.
I think Jake is on to something about the cookies. Make sure your browser at work is set to accept cookies from that domain. Make sure there isn't any antivirus/antimal-ware that has disabled this. I'd use fiddler to watch the traffic and headers on your work machine, and your home machine. you should be able to quickly spot the difference since it sounds like a client issue.
It could be that the computer at work isn't supporting session cookies. It's been a while since I last read about PHP Sessions, but from what I remember...
session_start() is called.
php checks to see if the browser has sent a cookie to the server (a unique identifier needs to be supplied.
if so, it then checks checks on the server for a file with the name of the session id
if successful, it parses the file and sets the variables into the $_SESSION array
Notice that step one of this process is to actually start the session with session_start() this needs to be called before any output at all.
Have you got session_start() before output?
Do you make use of session_start() in your various php files ?
One way to get around this problem could be to store your sessions in a database.
This DevShed article by Rich Smith is a good place to start:
Storing PHP Sessions in a Database
The session is no longer saved as a file on the server, but rather an entry in the DB, and should solve any cookie issues.
Are the settings in php.ini for session.auto_start the same in both ini's?
See http://de3.php.net/manual/en/session.configuration.php#ini.session.auto-start

Categories