Zend_Session and Expiration
-
27-05-2021 - |
Pregunta
I need to set a very short session (3 minutes) upon hitting a specific page on my site. If someone hits that page again during that 3 minute session, the session should update to expire 3 minutes from that time.
On my "bootstrap" (it isn't a typical Zend bootstrap, but it is included in every page), I do the following:
$aSessionSaveHandlerConfig = array
(
"name" => "Sessions",
"primary" => "Session_ID",
"modifiedColumn" => "UpdateTimestamp",
"dataColumn" => "Data",
"lifetimeColumn" => "Lifetime",
);
$oSaveHandler = new Zend_Session_SaveHandler_DbTable($aSessionSaveHandlerConfig);
$oSaveHandler->setLifetime(App::$ReservationTimeout)->setOverrideLifetime(true);
Zend_Session::setSaveHandler($oSaveHandler);
ini_set("session.cookie_lifetime",App::$ReservationTimeout);
$aSessionOptions = array
(
"gc_probability" => 100,
"gc_divisor" => 100,
"gc_maxlifetime" => App::$ReservationTimeout,
"cookie_lifetime" => App::$ReservationTimeout,
);
Zend_Session::setOptions($aSessionOptions);
Then within the page that should create/update the session, I have:
App::$ReservationSession = new Zend_Session_Namespace("ReservationSession");
$oSaveHandler = Zend_Session::getSaveHandler();
$oSaveHandler->setLifetime(App::$ReservationTimeout);
I see the records in the database, the lifetime column is correct, but if i repeatedly hit the page that creates/updates the session, I get a new Session ID after 3 minutes passes (and the other one gets removed after garbage collection.
It appears the problem is getting the cookie to update it's time. Any ideas?
Solución
To get the session cookie to update its expiration time, you can use Zend_Session::rememberMe() to change the default lifetime of the cookie. Calling rememberMe()
will also cause Zend_Session::regenerateId()
to be called which generates a new session ID, copies old session data to the new session, and sends a new session cookie to the browser.
Try the following code and see if it solves your problem:
App::$ReservationSession = new Zend_Session_Namespace("ReservationSession");
$oSaveHandler = Zend_Session::getSaveHandler();
$oSaveHandler->setLifetime(App::$ReservationTimeout);
// Call remember me which will send a new session cookie with 3 minute expiration
// from the current time. Old session data is copied to the new one and the old
// session is deleted
Zend_Session::rememberMe(App::$ReservationTimeout);
See the manual section on Session Identifiers for more information, or see also How to reset a Zend rememberMe function on each automatic login?
UPDATE: Given your comment, I came up with this solution that you can use.
What this does is start your session as usual and then checks a value in the session to see if the user had an existing session.
If they do have an session, it uses setcookie() to send an updated session cookie using the existing parameters (including session id), except it sets the expiration to time() + $ReservationTimeout
. If they did not have a session, then there is no need to update the cookie since the expiration is already correct and it will be updated on their next request (assuming they visit before it expires).
App::$ReservationSession = new Zend_Session_Namespace("ReservationSession");
$oSaveHandler = Zend_Session::getSaveHandler();
$oSaveHandler->setLifetime(App::$ReservationTimeout);
if (!isset(App::$ReservationSession->hasSession)) {
// user had no session before or it was expired
App::$ReservationSession->hasSession = true;
} else {
// user has a valid session, update the cookie to expire 3 mins from now
$params = session_get_cookie_params();
$expire = time() + App::$ReservationTimeout;
setcookie(session_name(),
Zend_Session::getId(),
$expire,
$params['path'],
$params['domain'],
$params['secure'],
$params['httponly']);
}
I tested the solution using the files session handler and it worked as expected, I think it should be fine for your situation as well.