Nette Http 3.1: much smarter sessions
Nette has Nette has always taken a cautious approach to sessions. It only started them automatically when users needed them. Which specifically means:
- when they write to it
- when they read from it and there is a session ID cookie
Because if the cookie doesn't exist, we don't need to run the session to know there's no data in it. So without running it, Nette might return the contents of the shopping cart as empty, etc.
Related to auto-starting is the problem of late session start, i.e. at a time
when the output has already been sent from the server and HTTP headers can no
longer be sent. When the session is started, a cookie with the session ID is
sent, as well as headers Pragma
and Expires
. In order
to minimize this problem, Nette, when set to autoStart:
smart, which is the default, automatically started the session at startup if
a session ID cookie existed.
However, there are some pitfalls that version 3.1.5 solves.
Data Access
Data in the session section is often accessed as variables:
$section = $session->getSection('unique name');
$section->userName = 'john';
echo $section->userName;
However, due to a specific technical limitation of PHP, the
echo $section->userName
operation is detected as a write. Thus,
even the above mentioned cart read $cart = $section->cart
will
start a session even if the cookie does not exist. Which spoils the efficiency
of autostart.
This could be avoided by using the ArrayAccess syntax:
$section['userName'] = 'john';
echo $section['userName']; // it is a read operation
However, the ArrayAccess syntax can be too magical for the user, and
sometimes doesn't work as one might expect (e.g.
$section['cart'][] = $item
generates a notice Indirect
modification of overloaded element has no effect). Therefore, in the latest
versions of the 3.1 and 3.0 series, you will find a comprehensible set of
methods set()
, get()
and remove()
for
accessing data. The expiration can also be set using set()
:
$section->set('flash', $message, '30 seconds');
Thus, using these methods becomes the preferred way to access data in sessions.
Autostart when a Cookie Exists
Nette modifies the behavior when the session ID turns out to be invalid, i.e. when there is no corresponding file on disk, etc. Nette detected such a situation and generated a new ID and a clean file to prevent a possible ID spoofing by an attacker. Now, instead, it deletes the cookie and does not create the file at all. The reason for this is to avoid creating empty files on disk if an attacker is intentionally spoofing the session ID.
New autoStart Configuration
Option autoStart
can now take new values always
and
never
. The always
turns on the session immediately
after startup and is identical to option true
. A new option is
never
, which turns off auto-start completely and only turns on the
session if you call $session->start()
. The default variant
remains smart
which, as mentioned above, no longer turns on the
session after startup, but only in the case of a read or write. It is actually
so identical to false
.
The v3.0 series changes the default from smart
to
false
, which also turns off autostart after startup.
Events $onStart, $onBeforeWrite
And finally, the Nette\Http\Session
object now has
$onStart
and $onBeforeWrite
events, so you can add
callbacks that fire after a session starts or before it is written to disk and
then terminated.
$session->onBeforeWrite[] = function () {
// zapíšeme data do session
$this->section->set('basket', $this->basket);
};
When testing the new behavior, keep in mind that Tracy starts a session in developer mode because it uses it to display redirect bars and AJAX requests in the Tracy Bar.
Sign in to submit a comment