I have a strange issue with a Laravel 5.1 application.
Intermittently, it’s dropping session data. I’m detected this by writing some middleware that writes the contents of the session for that request to the log file. Although the session ID (Session::getId()) doesn’t change, the value of _token in the session data retrieved with Session::all() does.
As I say, this happens intermittently. I can refresh the same URL multiple times, and then randomly on one refresh the session data’s gone, and the _token value’s different from the previous requests.
What would cause this? I’ve also noticed the flash object isn’t in the “dropped” session data.
Below is a snippet of the log. You can see the content of the session_data key randomly changes “shape” in the last two lines, but the session ID remains constant.
Also, not sure if it’s pertinent, but I have DebugBar enabled.
UPDATE: Through debugging, I’ve found that on some page loads the session is completely empty, as in, no _token (hence a new one getting generated). Nothing.
If you're using the file driver, you could run into race conditions on concurrent requests. The file then gets truncated, Laravel can't read it, so it refreshes the session. Race conditions can also lead to a symptom where something you're putting to the session just doesn't get put. This tends to be random, so it's very hard to debug. According to the Laravel team, this is a known limitation of the file driver and it does not appear to be getting fixed, so I would suggest using a different driver. This would fix your issue of random session refreshes, but it still introduces a possibility of making a change to the session that doesn't get added. As far as I know, at this point with Laravel 5.1, you'll have to manage that yourself.
Somehow your session data is too long and being truncated. If you're using the database driver (haven't tested other drivers), and you try to save session data that's longer than the field length, then subsequent requests won't be able to pull from this session, and you'll wind up with a new session. If this issue is happening randomly with very short session data, then it's probably the cause listed above.
If you use Linux, Try using Redis (http://redis.io) as session / cache manager in laravel. I had some issues in the past with text / cookies and laravel in some servers. When I instaled Redis I had no problems anymore.
More info: https://laravel.com/docs/5.1/redis
Using a different driver like memcached did not solve the problem for me.
Here is a package that implements session locking which works and very simple to incorporate in your projects.
https://github.com/rairlie/laravel-locking-session
Related
Long story short: I have hacked jasny/sso to work with Laravel. It works extremely well except when the primary/root session has expired.
I have the primary/root authentication set to "remember", so it can reauthenticate from the cookie when the session has expired.
When the 'attach' action happens on the SSO server and the primary/root session has already expired, I am running Auth::check() to bring the session back to life so that it can be attached properly.
All of my debugging indicates that everything is working exactly as I need it to except for this one little detail:
The new session generated by the 'attach' action is never written to the database because the DatabaseSessionHandler thinks it already exists. It is running an UPDATE instead of an INSERT.
As a result, my SSO client session attaches to a non-existent SSO server session.
For the life of me, I can not figure out why it thinks this new session already exists nor how to get it to correctly insert into the database.
Can anyone tell me why a new Laravel 4.2 session would be detected as "exists" and run UPDATE instead of INSERT on save()?
EXTRA DEBUGGING ATTEMPTS --
Attempt #1: I have tracked this to a false attachment to an expired session that hasn't been garbage collected yet. What I don't understand is how this session is being loaded while a different session ID is being presented. If this were the result of the migrate() or regenerate() methods, "exists" would be set to false, and it would save correctly. Somehow, it seems that the session ID is being updated without resetting "exists".
Attempt #2: The answer was staring me in the face the whole time. I kind of understand the downvote now. (see my answer below)
I was dramatically over-thinking this as I tried to uncover the mechanism behind the behavior instead of testing what looked like an easy solution:
If I call Session::setExists(false) prior to Session::save(), it will insert the new session correctly.
EDIT: If wrapped in an if-statement for Auth::viaRemember(), I can check if the auth happened via session or cookie/remember. If true, then I want to set "exists" to false.
I have a page which will send some ajax request to my Jetty7.6.9 server. All of them containing a COOKIE named JSESSIONID so that the server knows the request is logged in.
But sometimes, the method org.eclipse.jetty.server.Request.getCookies() returns an empty Cookie[]. I set a breakpoint and checked the _connection._requestFields and I found the Cookie right there, but Request.getCookies() cannot fetch it or parse it.
The situation can happen in any one or more ajax request in that page, can happen in any time, can happen in both windows and linux. It seems that it's a random case, and even when I dropped the frame at the breakpoint to the pre line, it would run correctly when it ran to the same place, so I think it's an issue about synchronize/concurrent.
I didn't find the same case in jetty bug list.
Is it a bug? What can I do to verify or repeat it? How to fix it?
(For some reason,maybe I cannot update the Jetty version for our system.)
i already posted this question but still wasnt able to resolve this issue.
seems that everyone has this problem with codeigniter .
When i set my session in a controller it works perfectly and i can display it.
WHen i move to another controller, the (CUSTOM) session data is completely lost.
i tried changing my cookie_domain in config.php. Since i am on localhost i tried localhost with without / and localhost/codeigniter and sodeigniter all did not work. i am lost
btw, i read somewhere that this happens when 2 ajax requests happen at the same time. could that be the problem?
Or maybe tell me how you resolved the problem if you had same issues
screw this, i am swithing to php native sessions. if anyone wants to do that,
http://codeigniter.com/wiki/PHPSession
Check and double-check your code or any external libraries you are using for a stray sess_destroy(). I ran into a similar problem where I was storing an id in the session for reference but if the user then logs in the SimpleLogin library I was using for logins just destroys the entire session including data I did not want to lose.
This is what I get for not writing my own code.
There are plenty of examples of similar problems littered around the web but none of their solutions seem to fix this particular variation. Any suggestions would be appreciated.
Usually this problem occurs because a rogue link is causing a request for a resources like a favicon or css file to hit the dispatcher more than once, thus causing multiple dispatch processes and therefore multiple rows in your database.
I have checked that all the links on this very simple example page do actually resolve to the resource to which they point.
The session handler is setup as follows:
Zend_Db_Table_Abstract::setDefaultAdapter($db);
Zend_Session::setSaveHandler(new
Zend_Session_SaveHandler_DbTable($config->session->toArray()));
The db logging is setup as follows:
$writer = new Zend_Log_Writer_Db($db, $config->log->tableName,
$config->log->columnMap->toArray());
$logger = new Zend_Log($writer);
Both objects are correctly setup and can read and write to and from the database. Only everything happens twice. If I put a test log message anywhere in the application it is written into the database twice. If I increment three variables with every call to the index action - one stored in the session, one passed around via a Zend_Registry object and another local to the indexAction - only the session variable is incremented by 2. The Apache access log shows the correct amount of requests being fired from the page load and all have good response codes of either 200 or 304 (unchanged).
I have tried disabling all head links.
I have tried disabling the layout entirely.
I have localised everything to the dispatcher and exited before dispatch is run.
In all cases the extra write/increment takes place.
Any thoughts?
Thanks in advance for any help.
I seem to have found and fixed the issue. Chrome (and possibly all Webkit browsers) issues an additional HEAD request on top of the GET which means the application is hit twice and anything session based will be triggered as a result of both requests. My temporary solution is to put the following code near the start of my index.php file.
if ("HEAD" == $_SERVER['REQUEST_METHOD']) {
exit;
}
I hope that helps anyone with the same issue.
Google Chrome always asks for the favicon.ico by making annoying requests to the server. Take care about this in Chrome.
For more information:
http://framework.zend.com/issues/browse/ZF-11502?page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#issue-tabs
Thanks to the Sebastian Galenski contribution.
I'm using Zend Framework for PHP and handling sessions with the Zend_Session module. This is what I have in my Initializer (or bootstrap):
Zend_Session::start();
Zend_Session::rememberMe(864000);
864000 seconds should be good for 10 days, but I'm still being kicked out at about an hour (or maybe a little less). I've tested to see if this statement works at all by setting it to 10 seconds, and indeed I am kicked out at the appropriate time, but when I set it to a very high value, it doesn't work! I went through some of the documentation here:
http://framework.zend.com/manual/en/zend.session.html
Another method I saw was to use the following:
$authSession = new Zend_Session_Namespace('Zend_Auth');
$authSession->setExpirationSeconds(3600);
Now, I have different namespaces. Does this mean I have to set this for all of them if I want to keep them from expiring? I haven't tested this method of setting the expiration, but I really wanted to see what the gurus on here had to say about what the correct way of approaching this problem is. Thanks a lot guys...
Also, does anyone know how I can make it so that the session never expires? I've tried setting the second to 0 and -1, but that throws an error.
I had the same problem and solved it by putting:
resources.session.save_path = APPLICATION_PATH "/../data/session/"
resources.session.gc_maxlifetime = 864000
resources.session.remember_me_seconds = 864000
in the application.ini (as suggested by tawfekov) and
protected function _initSessions() {
$this->bootstrap('session');
}
in the Bootstrap.php (this I typically forgot at first). You have to give the session directory the correct access rights (chmod 777). I described the issue here. Hopefully this will help the next person with the same issue.
Your client's computer clock, date, AND time zone need to be set correctly for session expirations to work. Otherwise the time conversions are off, and likely causing your cookie to expire the minute it hits the their browser.
Try calling remember me before starting the session:
Zend_Session::rememberMe(864000);
Zend_Session::start();
Otherwise I believe it will use the default of remember_me_seconds. See 49.4.4. rememberMe(integer $seconds)
Also, does anyone know how I can make
it so that the session never expires?
I've tried setting the second to 0 and
-1, but that throws an error.
I don't think that is possible. The session is controlled by whether the cookie exists on the users computer. Those cookies can be deleted, even by the users if they clear their cache. I think the best you can do is set it to a very large number. Say 12 months.
I guess you are using ZF 1.8 or above ,
so you can put in the config.ini file
resources.session.save_path = APPLICATION_PATH "/../data/session"
resources.session.remember_me_seconds = 864000
and these setting will automatically loaded
again only in ZF 1.8 or above if not you had to load these config manually
i hope it helps you :)
Are there other PHP applications running on the server?
Assuming you're using the standard, file-based, session handler, PHP will store all sessions in the same place (typically /tmp).
If you have some other script on the server using the default session_gc_maxlifetime settings, it may be eating your session files.
The easiest fix to try is to configure PHP to store session files for this application someplace special -- that way other apps running on the server will never accidently "clean up" session data from this app.
Try creating a directory like /tmp/myAppPhpSessions (or whatever), and adding:
ini_set('session.save_path','/tmp/myAppPhpSessions');
ini_set('session.gc_maxlifetime', 864000);
at the very top of your bootstrap file.
Make sure session.auto_start is off in php.ini