Ask your Symfony questions! Pay money and get answers fast! (more info)

Redirection on timeout Symfony

  • SOLVED

I implemented an action that checks whether the user is still logged in or not, and with jquery, I make an ajax call to this action after the timeout value from factories.yml. If the user has been timed out, I redirect the user to the homepage.

This works fine with just one tab, cause if there are two or more tabs, when the first tab checks it will not still be timeout (since a new tab was opened). The problem is that just by calling this action I'm making the timeout start all over again, so if I have two tabs opened the site will never timeout (the ajax calls will keep it active).

Is there any way in Symfony to check for timeout without having this very same action restart the timer?

I would like to implement a redirection system on my site to that if the user logs out in one tab, all the other tabs will shortly redirect to the homepage, but I just can't figure out how to do this in Symfony.

Answers (1)

2011-02-21

Gergely Szilagyi answers:

Hi!
My tip is following - step by step:

(1)
Put the expire time into app.yml :

all:
project:
my_expire_ttl: 3600 # this means 1 hour


(2)
On first visit put one session on server - for example at login.
In login action , you set the expire timestamp , "global":


if( ! $this->getUser()->hasAttribute('my_expire') OR $this->getUser()->getAttribute('my_expire') < time() )
{
$this->getUser()->setAttribute('my_expire', sfConfig::get('app_project_my_expire_ttl') + time() );
}


(3)
You make an action, only for check the TTL expiring , later for ajax calls:



public function executeCheckMyExpire(sfWebRequest $request )
{

$need_redirect = "";
if(
$request->isXmlHttpRequest()
AND
(
! $this->getUser()->isAuthenticated()
OR
$this->getUser()->getAttribute('my_expire') < time()
)
)
{
// in this case, you know its time to redirect!
$need_redirect = "YOUR LINK TO REDIRECT IN AJAX RESPONSE";
}

return $this->renderText($need_redirect);
}



(4)
Finally in the template :


<script>
var only_one_in_one_time_flag = true;

function checkExpire()
{
// only run the function in one thread!
if(only_one_in_one_time_flag)
{
only_one_in_one_time_flag = false;
jQuery.get("__MODULE__/checkMyExpire", function (data) {
data = jQuery.trim(data);

if(data.length > 10)
{
// you know, redirect need, cause there is a string
window.location.href = data;
}else
{
// do nothing, cause the user is already logged in, or the expire flag is still alive.
}
// if the async call is ended, then function is callable again
only_one_in_one_time_flag = true;
});

}
}

setInterval("checkExpire()",10000); // in 10 sec in enougth to call
</script>





******-
Thats it, you can make this with cookies, or other tricks too, but this is the most simple - i think.

I hope, i could help you!
Best regards :
Gergely Szilagyi


fxsymfony comments:

Hi Gergely,

your solutions seems good to check on open tabs if the user logged out in one tab, or for having a general limit time to use the site, but I don't see how it will help you with the inactivity timeout.. doesn't executeCheckMyExpire() prevents the site for ever timing out of inactivity?


Gergely Szilagyi comments:

Hi!

You have right, but then the problem is more easy, when you interesting only for "inacitve timing" on client side.

Include this script : http://plugins.jquery.com/files/jquery.cookie.js.txt ( https://github.com/carhartl/jquery-cookie ).

Script in layout : set a cookie (with expected ttl ) on pageload, and check every ~10 sec the ttl, when it dies, redirect. This should be work for more browser-tab too. ( care just the last opened tab, and when the ttl comes, redirect tabs together )

You can make your life simplier, when the client custom cookie expire, and the symfony session lifetime match, cause this case the client and the server side functionality is in sync.

I hope, i could help.
Ciao


fxsymfony comments:

Ok I've got an idea which is using part of the implementation you posted, but updating the $this->getUser()->getAttribute('my_expire') in a filter,

This filter will only update this expiration time if the action that is being called is different from the checking action CheckMyExpire, that will be called with AJAX every 20 seconds or so.

Now here is the question, how do you obtain the name of the action that is being called for when you are in a filter?


Gergely Szilagyi comments:

if(sfContext::hasInstance())
{
$name_of_current_action = sfContext::getInstance()->getActionName();
$name_of_current_module = sfContext::getInstance()->getModuleName();
}


Good luck ;)
This works everywhere inside your project, when the code is called from web.