HOWTO: Disable Session Timeout in Symfony
Wed 16 Jan 2008 by Rob RosenbaumThe problem: make symfony use PHP's default session behavior. Symfony session handling is based on timed sessions - you set a time after which the session will expire - but the default PHP behavior is to expire when the user closes the browser window. This is also the most commonly desired behavior for sessions. The drawback of using a timed session is that it could expire while the user is still on the site. This is an issue in LectureTools, because students may sit for an hour or more without loading a new page, and they may even have logged in before class. You can solve this little problem easily if you are using symfony 1.1 (currently in beta). Just set the timeout to false in settings.yml:
all:
.settings:
timeout: false
But if you are using the stable 1.0 branch of symfony, this will do just the opposite - it will make your sessions time out immediately! To make this work, we have to override sfBasicSecurityUser's initialize() method. I will describe two ways to do this; one is a short hack, the other is longer and somewhat more proper.
Here's the short way:
class myUser extends sfBasicSecurityUser
{
public function initialize($context, $parameters = null)
{
if (sfConfig::get('sf_timeout') == 0) {
// session will expire if window is open for a day
sfConfig::set('sf_timeout', 86400);
}
return parent::initialize($context, $parameters);
}
}
This works because the sf_timeout setting is not used by any other class (at the moment), so changing it doesn't have any side effects. If you set your timeout to 0 or false, symfony will always think you have set the session timeout to 24 hours, but the session will actually expire when the user closes the browser window.
If you are not comfortable with "hacks" like the above, you could copy the initialize() method from sfBasicSecurityUser, change it in the appropriate place, and skip calling the parent constructor altogether. Unfortunately, sfBasicSecurityUser calls its parent constructor, so you have to rewrite them both:
class myUser extends sfBasicSecurityUser
{
public function initialize($context, $parameters = null)
{
$this->context = $context;
$this->parameterHolder = new sfParameterHolder();
$this->parameterHolder->add($parameters);
$this->attributeHolder = new sfParameterHolder(self::ATTRIBUTE_NAMESPACE);
// read attributes from storage
$attributes = $context->getStorage()->read(self::ATTRIBUTE_NAMESPACE);
if (is_array($attributes))
{
foreach ($attributes as $namespace => $values)
{
$this->attributeHolder->add($values, $namespace);
}
}
// set the user culture to sf_culture parameter if present in the request
// otherwise
// - use the culture defined in the user session
// - use the default culture set in i18n.yml
if (!($culture = $context->getRequest()->getParameter('sf_culture')))
{
if (null === ($culture = $context->getStorage()->read(self::CULTURE_NAMESPACE)))
{
$culture = sfConfig::get('sf_i18n_default_culture', 'en');
}
}
$this->setCulture($culture);
// read data from storage
$storage = $this->getContext()->getStorage();
$this->authenticated = $storage->read(self::AUTH_NAMESPACE);
$this->credentials = $storage->read(self::CREDENTIAL_NAMESPACE);
$this->lastRequest = $storage->read(self::LAST_REQUEST_NAMESPACE);
if ($this->authenticated == null)
{
$this->authenticated = false;
$this->credentials = array();
}
else
{
// Automatic logout logged in user if no request within [sf_timeout] setting
if (0 != sfConfig::get('sf_timeout') && null !== $this->lastRequest && (time() - $this->lastRequest) > sfConfig::get('sf_timeout'))
{
if (sfConfig::get('sf_logging_enabled'))
{
$this->getContext()->getLogger()->info('{sfUser} automatic user logout due to timeout');
}
$this->setTimedOut();
$this->setAuthenticated(false);
}
}
$this->lastRequest = time();
}
}
That should do it!
19 Comments Add your own
1. Brett | January 17th, 2008 at 1:34 pm
What timing. I was just beginning to search for a solution to my timeout problems. And BAM you have a solution.
Unfortunately, it didn't work. I am using sfGuardDoctrine on Symfony 1.0.10 and tried the quick hack solution to no avail. Do you have any recommendations for troubleshooting this when it doesn't work?
Thanks.
2. Rob Rosenbaum | January 17th, 2008 at 4:16 pm
Brett-
The sfGuard* plugins use a separate cookie management system. It looks like the code for this is located entirely in the
signIn()method of thesfGuardSecurityUserclass, so you would have to override that method in yourmyUserclass.3. hartym | January 18th, 2008 at 11:31 am
I don't understand the point in doing that, why dont you just set timeout to 86400 in settings.yml?
4. digitalbase | January 18th, 2008 at 11:41 am
i don't think this solution works…
5. Rob Rosenbaum | January 18th, 2008 at 11:55 am
hartym-
The idea is to make symfony 1.0 respond intuitively to settings.yml. As a PHP developer, I expect "0" to mean forever. The 86400 could be set to an even larger number, of course. The second, longer solution in the article is actually the more appropriate one, since it creates a true untimed session.
digitalbase-
Any details, or are you just SEOing your website?
6. rpsblog.com » A wee&hellip | January 20th, 2008 at 6:00 pm
[...] HOWTO: Disable Session Timeout in Symfony [...]
7. Symfony.es » Blog A&hellip | February 3rd, 2008 at 6:04 am
[...] HOWTO: Disable Session Timeout in Symfony [...]
8. fluffigt.com » Blog&hellip | February 5th, 2008 at 5:23 pm
[...] HOWTO: Disable Session Timeout in Symfony (tags: symfony tips) [...]
9. fluffigt.com » Blog&hellip | April 12th, 2008 at 8:46 am
[...] http://robrosenba…; [...]
10. Large Lee | May 2nd, 2008 at 10:20 pm
Hi,
Does anyone know how to defeat a webpage from timeing out after a certain amount of time?
Is there a simple piece of software that will periodically conduct some activity at the users end on the page so the time-out perpetually resets itself and the page won't close?
Thanks!
11. Edowardo | May 15th, 2008 at 5:21 am
Good solution. Just simple it is.
Can implement without security matters ya!
12. » Store Symfony Ses&hellip | May 21st, 2008 at 5:03 pm
[...] http://robrosenbaum.com/php/howto-disable-session-timeout-in-symfony/ [...]
13. » Store Symfony Ses&hellip | May 23rd, 2008 at 12:17 pm
[...] http://robrosenbaum.com/php/howto-disable-session-timeout-in-symfony/ [...]
14. thichquay | May 25th, 2008 at 10:36 am
hello,
how can I reference the new myUser class (I'm using the 1st method)? Also, where should I place this class at?
Thankns
newbie
15. thichquay | May 25th, 2008 at 10:40 pm
I created a myUser.class.php under lib folder but however, I don't think this method is working (settings.yml was set with timeout = false as well). Please help…
THanks
16. Sebastian | June 30th, 2008 at 3:46 am
Rob,
there is no difference between PHP and sf session handling. In fact, AFAIK sf uses PHP file based session handler by default.
Independent of the storage, the session system never detects browser close, it always does its gc based on the timestamp of the last request. Each request updates a timestamp of or in the session file/database entry.
But for sure its ok to disable this system if it doesn't work for you (because of times of long activity).
I just wanted to state that there is no difference in principal between sf and PHP session handling!
Sebastian
17. Colnector | October 9th, 2008 at 4:05 am
As I've had trouble making this work with Symfony 1.1, here's my small patch. It's for the same initialize() function mentioned here.
public function initialize(sfEventDispatcher $dispatcher, sfStorage $storage, $options = array()) {
$options['timeout'] = 86400; # 1 day - or set to as long as you want
parent::initialize($dispatcher, $storage, $options);
}
18. Rajeevr | November 4th, 2008 at 2:18 am
Hi,
I put timeout as 1 in settings.yml
But the session is not clearing!!!
Tel me whats the problem??
19. Larry Weya | February 25th, 2009 at 7:43 am
http://www.symfony-project.org/installation/1_1/upgrade#Session%20timeout
Set it in factories.yml for symfony 1.1
Leave a Comment
Please: No emoticons or excessive punctuation.Trackback this post | Subscribe to the comments via RSS Feed