Wednesday 25 October 2017

How do I expire a PHP session after 30 minutes?

style="font-weight: bold;">

Answer



style="font-weight: bold;">

Answer





I need to keep a session alive for
30 minutes and then destroy it.


class="post-text" itemprop="text">
class="normal">Answer



You should
implement a session timeout of your own. Both options mentioned by others ( href="http://php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime"
rel="noreferrer">session.gc_maxlifetime and href="http://php.net/manual/en/session.configuration.php#ini.session.cookie-lifetime"
rel="noreferrer">session.cookie_lifetime) are not
reliable. I'll explain the reasons for
that.




First:





session.gc_maxlifetime />session.gc_maxlifetime specifies the number of seconds after
which data will be seen as 'garbage' and cleaned up. Garbage collection occurs during
session start.




But
the garbage collector is only started with a probability of href="http://php.net/manual/en/session.configuration.php#ini.session.gc-probability"
rel="noreferrer">session.gc_probability divided by
rel="noreferrer">session.gc_divisor. And using the
default values for those options (1 and 100 respectively), the chance is only at
1%.



Well, you could simply adjust these values
so that the garbage collector is started more often. But when the garbage collector is
started, it will check the validity for every registered session. And that is
cost-intensive.




Furthermore, when
using PHP's default href="http://php.net/manual/en/session.configuration.php#ini.session.save-handler"
rel="noreferrer">session.save_handler files, the
session data is stored in files in a path specified in href="http://php.net/manual/en/session.configuration.php#ini.session.save-path"
rel="noreferrer">session.save_path. With that session
handler, the age of the session data is calculated on the file's last modification date
and not the last access
date:





Note: If you are using the default file-based
session handler, your filesystem must keep track of access times (atime). Windows FAT
does not so you will have to come up with another way to handle garbage collecting your
session if you are stuck with a FAT filesystem or any other filesystem where atime
tracking is not available. Since PHP 4.2.3 it has used mtime (modified date) instead of
atime. So, you won't have problems with filesystems where atime tracking is not
available.




So it
additionally might occur that a session data file is deleted while the session itself is
still considered as valid because the session data was not updated
recently.



And
second:






session.cookie_lifetime />session.cookie_lifetime specifies the lifetime of the cookie
in seconds which is sent to the browser.
[…]




Yes, that's
right. This only affects the cookie lifetime and the session itself may still be valid.
But it's the server's task to invalidate a session, not the client. So this doesn't help
anything. In fact, having session.cookie_lifetime set to
0 would make the session’s cookie a real href="http://en.wikipedia.org/wiki/HTTP_cookie#Session_cookie"
rel="noreferrer">session cookie that is only valid until the browser is
closed.



Conclusion / best
solution:



The best solution is to
implement a session timeout of your own. Use a simple time stamp that denotes the time
of the last activity (i.e. request) and update it with every
request:




if
(isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] >
1800)) {
// last request was more than 30 minutes ago

session_unset(); // unset $_SESSION variable for the run-time

session_destroy(); // destroy session data in
storage
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last
activity time
stamp


Updating the
session data with every request also changes the session file's modification date so
that the session is not removed by the garbage collector
prematurely.




You can also use an
additional time stamp to regenerate the session ID periodically to avoid attacks on
sessions like rel="noreferrer">session
fixation
:



if
(!isset($_SESSION['CREATED'])) {
$_SESSION['CREATED'] = time();
}
else if (time() - $_SESSION['CREATED'] > 1800) {
// session started more
than 30 minutes ago
session_regenerate_id(true); // change session ID for the
current session and invalidate old session ID
$_SESSION['CREATED'] = time();
// update creation
time
}



Notes:




  • session.gc_maxlifetime
    should be at least equal to the lifetime of this custom expiration handler (1800 in this
    example);

  • if you want to expire the session after 30
    minutes of activity instead of after 30 minutes since
    start
    , you'll also need to use setcookie with an
    expire of time()+60*30 to keep the session cookie
    active.


No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...