Skip to content

Commit 022c162

Browse files
committed
Merge pull request #1191 from drak/sessiongc
[HttpFoundation] Information about garbage collection and session expiry
2 parents aa6af43 + 2ae30dc commit 022c162

File tree

1 file changed

+155
-15
lines changed

1 file changed

+155
-15
lines changed

components/http_foundation.rst

Lines changed: 155 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,8 @@ abstracts the hard work behind a simple API::
375375

376376
$response->headers->set('Content-Disposition', $d);
377377

378-
Session
379-
-------
378+
Sessions
379+
--------
380380

381381
The Symfony2 HttpFoundation Component has a very powerful and flexible session
382382
subsystem which is designed to provide session management through a simple
@@ -391,7 +391,7 @@ implementation of :class:`Symfony\\Component\\HttpFoundation\\Session\\SessionIn
391391

392392
Quick example::
393393

394-
use Symfony\\Component\\HttpFoundation\\Session\\Session;
394+
use Symfony\Component\HttpFoundation\Session\Session;
395395

396396
$session = new Session();
397397
$session->start();
@@ -424,9 +424,12 @@ Session workflow
424424

425425
* :method:`Symfony\\Component\\HttpFoundation\\Session\\Session::migrate`:
426426
Regenerates the session id - do not use ``session_regenerate_id()``.
427+
This method can optionally change the lifetime of the new cookie that will
428+
be emitted by calling this method.
427429

428430
* :method:`Symfony\\Component\\HttpFoundation\\Session\\Session::invalidate`:
429431
Clears the session data and regenerates the session id do not use ``session_destroy()``.
432+
This is basically a shortcut for ``clear()`` and ``migrate()``.
430433

431434
* :method:`Symfony\\Component\\HttpFoundation\\Session\\Session::getId`: Gets the
432435
session ID.
@@ -480,6 +483,12 @@ an array. A few methods exist for "Bag" management:
480483
Gets the :class:`Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBagInterface`.
481484
This is just a shortcut for convenience.
482485

486+
Session meta-data
487+
488+
* :method:`Symfony\\Component\\HttpFoundation\\Session\\Session::getMetadataBag`:
489+
Gets the :class:`Symfony\\Component\\HttpFoundation\\Session\\Storage\MetadataBag`
490+
which contains information about the session.
491+
483492
Save Handlers
484493
~~~~~~~~~~~~~
485494

@@ -511,9 +520,9 @@ Symfony2 provides drivers for native handlers which are easy to configure, these
511520

512521
Example of use::
513522

514-
use Symfony\\Component\\HttpFoundation\\Session\\Session;
515-
use Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage;
516-
use Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeMemcachedSessionHandler;
523+
use Symfony\Component\HttpFoundation\Session\Session;
524+
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
525+
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeMemcachedSessionHandler;
517526

518527
$storage = new NativeSessionStorage(array(), new NativeMemcachedSessionHandler());
519528
$session = new Session($storage);
@@ -535,9 +544,9 @@ examples if you wish to write your own.
535544

536545
Example::
537546

538-
use Symfony\\Component\\HttpFoundation\\Session\\Session;
539-
use Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorage;
540-
use Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\PdoSessionHandler;
547+
use Symfony\Component\HttpFoundation\Session\Session;
548+
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorage;
549+
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
541550

542551
$storage = new NativeSessionStorage(array(), new PdoSessionHandler());
543552
$session = new Session($storage);
@@ -704,7 +713,7 @@ to be used for more complex messaging in your application.
704713

705714
Examples of setting multiple flashes::
706715

707-
use Symfony\\Component\\HttpFoundation\\Session\\Session;
716+
use Symfony\Component\HttpFoundation\Session\Session;
708717

709718
$session = new Session();
710719
$session->start();
@@ -774,8 +783,8 @@ For unit testing where it is not necessary to persist the session, you should
774783
simply swap out the default storage engine with
775784
:class:`Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockArraySessionStorage`::
776785

777-
use Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockArraySessionStorage;
778-
use Symfony\\Component\\HttpFoundation\\Session\\Session;
786+
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
787+
use Symfony\Component\HttpFoundation\Session\Session;
779788

780789
$session = new Session(new MockArraySessionStorage());
781790

@@ -786,8 +795,8 @@ For functional testing where you may need to persist session data across
786795
separate PHP processes, simply change the storage engine to
787796
:class:`Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorage`::
788797

789-
use Symfony\\Component\\HttpFoundation\\Session\\Session;
790-
use Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorage;
798+
use Symfony\Component\HttpFoundation\Session\Session;
799+
use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage;
791800

792801
$session = new Session(new MockFileSessionStorage());
793802

@@ -833,5 +842,136 @@ The proxy mechanism allow you to get more deeply involved in session save handle
833842
classes. A proxy for example could be used to encrypt any session transaction
834843
without knowledge of the specific save handler.
835844

845+
Configuring PHP Sessions
846+
~~~~~~~~~~~~~~~~~~~~~~~~
847+
848+
The :class:`Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage`
849+
can configure most of the PHP ini configuration directives which are documented
850+
at `php.net/session.ini`_
851+
852+
To configure these setting pass the keys omitting the initial ``session.`` part
853+
of the key as key to value pairs in an array to the ``$options`` parameter in
854+
the constructor, or optionally using the
855+
:method:`Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage::setOptions`
856+
method.
857+
858+
For the sake of clarity, some key options are explained in this documentation.
859+
860+
Session Cookie Lifetime
861+
~~~~~~~~~~~~~~~~~~~~~~~
862+
863+
For security, session tokens are generally recommended sent as session cookies.
864+
You can configure the lifetime of session cookies by specifying the lifetime
865+
(in seconds) using the ``cookie_lifetime`` key in the constructor's ``$options``
866+
argument in :class:`Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage`.
867+
868+
Setting a ``cookie_lifetime`` to ``0`` will cause the cookie to live only as
869+
long as the browser remains open. Generally, ``cookie_lifetime`` would be set to
870+
a relatively large number of days, weeks or months. It is not uncommon to set
871+
cookies for a year or more depending on the application.
872+
873+
Since session cookies are just a client-side token, they are less important in
874+
controlling the fine details of your security settings which ultimately can only
875+
be securely controlled from the server side.
876+
877+
.. note::
878+
879+
The ``cookie_lifetime`` setting is the number of seconds the cookie should live
880+
for, it is not a Unix timestamp. The resulting session cookie will be stamped
881+
with an expiry time of ``time()``+``cookie_lifetime`` where the time is taken
882+
from the server.
883+
884+
Configuring Garbage Collection
885+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
886+
887+
When a session opens, PHP will call the ``gc`` handler randomly according to the
888+
probability set by ``session.gc_probability`` / ``session.gc_divisor``. For
889+
example if these were set to ``5/100`` respectively, it would mean a probability
890+
of 5%. Similarly, ``3/4`` would mean a 3 in 4 chance of being called, ie 75%.
891+
892+
If the garbage collection handler is invoked, PHP will pass the value stored in
893+
the PHP ini directive ``session.gc_maxlifetime`. The meaning in this context is
894+
that any stored session that was saved more than ``maxlifetime`` should be
895+
deleted. This allows one to expire records based on idle time.
896+
897+
You can configure these settings by passing ``gc_probability``, ``gc_divisor``
898+
and ``gc_maxlifetime`` in an array to the constructor of
899+
:class:`Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage`
900+
or to the :method:`Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage::setOptions()`
901+
method.
902+
903+
Session Lifetime
904+
~~~~~~~~~~~~~~~~
905+
906+
When a new session is created, meaning Symfony2 issues a new session cookie
907+
to the client, the cookie will be stamped with an expiry time. This is
908+
calculated by adding the PHP runtime configuration value in
909+
``session.cookie_lifetime`` with the current server time.
910+
911+
.. note::
912+
913+
PHP will only issue a cookie once. The client is expected to store that cookie
914+
for the entire lifetime. A new cookie will only be issued when the session is
915+
destroyed, the browser cookie is deleted, or the session ID is regenerated
916+
using the ``migrate()`` or ``invalidate()`` methods of the ``Session`` class.
917+
918+
The initial cookie lifetime can be set by configuring ``NativeSessionStorage``
919+
using the ``setOptions(array('cookie_lifetime' => 1234))`` method.
920+
921+
.. note::
922+
923+
Cookie lifetime of ``0`` means the cookie expire when the browser is closed.
924+
925+
Session Idle Time/Keep Alive
926+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
927+
928+
There are often circumstances where you may want to protect, or minimize
929+
unauthorized used of a session when a user steps away from their terminal while
930+
logged in by destroying the session after a certain period of idle time. For
931+
example, it is common for banking applications to log the user out after just
932+
5 to 10 minutes of inactivity. Setting the cookie lifetime here is not
933+
appropriate because that can be changed at the client, so we must do the expiry
934+
on the server side. The easiest way is to implement this via garbage collection
935+
which runs reasonably frequently: So the cookie ``lifetime`` would be set to a
936+
relatively high value, and the garbage collection ``maxlifetime`` would be set
937+
to destroy sessions at whatever the desired idle period is.
938+
939+
The other option is to specifically checking if a session has expired after the
940+
session is started. The session can be destroyed as required. This method of
941+
processing can allow the expiry of sessions to be integrated into the user
942+
experience, for example, by displaying a message.
943+
944+
Symfony2 records some basic meta-data about each session to give you complete
945+
freedom in this area.
946+
947+
Session meta-data
948+
~~~~~~~~~~~~~~~~~
949+
950+
Sessions are decorated with some basic meta-data to enable fine control over the
951+
security settings. The session object has a getter for the meta-data,
952+
:method:`Symfony\Component\HttpFoundation\Session\Session::getMetadataBag` which
953+
exposes an instance of :class:`Symfony\Component\HttpFoundation\Session\Storage\MetadataBag`::
954+
955+
$session->getMetadataBag()->getCreated();
956+
$session->getMetadataBag()->getLastUsed();
957+
958+
Both methods return a Unix timestamp (relative to the server).
959+
960+
This meta-data can be used to explicitly expire a session on access, e.g.::
961+
962+
$session->start();
963+
if (time() - $session->getMetadataBag()->getLastUpdate() > $maxIdleTime) {
964+
$session->invalidate();
965+
throw new SessionExpired(); // redirect to expired session page
966+
}
967+
968+
It is also possible to tell what the ``cookie_lifetime`` was set to for a
969+
particular cookie by reading the ``getLifetime()`` method::
970+
971+
$session->getMetadataBag()->getLifetime();
972+
973+
The expiry time of the cookie can be determined by adding the with the created
974+
timestamp and the lifetime.
836975

837-
.. _`php.net/session.customhandler`: http://php.net/session.customhandler
976+
.. _`php.net/session.customhandler`: http://php.net/session.customhandler
977+
.. _`php.net/session.configuration`: http://php.net/session.configuration

0 commit comments

Comments
 (0)