prepare for release
refer to "Releases"
remove other references to sr.ht
Summary: Modern HTTP cookie and session library
Description: An easy to use, secure, simple and modern PHP cookie and session library supporting multiple parallel sessions without using PHP's built-in session management.
License: MIT
This is an easy to use, secure, simple and modern PHP cookie and session library supporting multiple parallel sessions without using PHP's built-in session management.
Many thanks to Jørn Åne de Jong (Uninett) for invaluable feedback during the development.
The existing PHP way of using and configuring cookies and sessions is
complicated and not secure by default. It has various configuration flags in
php.ini
that also vary in different versions of PHP.
For our purposes we also require support of multiple parallel sessions, this is
very complicated with PHP's session management. With the introduction of the
SameSite
cookie value, this became even more important as in some situations
it is recommended to use multiple sessions in parallel with different
SameSite
values, see e.g. section 8.8.2 of
Cookies: HTTP State Management Mechanism.
Uses only core PHP extensions, no other dependencies.
Currently php-secookie is not hosted on Packagist. It
may be added in the future. To use the library, you can add this to your
composer.json
:
{
"repositories": [
{
"type": "vcs",
"url": "https://codeberg.org/fkooman/php-secookie"
}
],
"require": {
"fkooman/secookie": "^6"
}
}
You can also download the signed source code archive from the project page under "Releases".
Create a cookie foo
with the value bar
:
$myCookie = new fkooman\SeCookie\Cookie();
if(null === $cookieValue = $myCookie->get('foo')) {
// no value for cookie "foo" (yet)
$myCookie->set('foo', 'bar');
}
Start a new session, store a key foo
with value bar
, get the session value
again, remove it and stop the session:
$mySession = new fkooman\SeCookie\Session();
$mySession->start();
$mySession->set('foo', 'bar');
echo $mySession->get('foo');
$mySession->remove('foo');
$mySession->stop();
Note that stopping the session is also done automatically at the end of the script by the destructor, so only call this if you need to stop the session and write the session data to storage.
Calling Session::set
or Session::remove
will always give a new session and
destroy the old session, there is no need to manually "regenerate". When
designing your application, only modify your session data when needed, e.g.
during authentication, not on every page load.
You can also completely destroy the session and remove the session data:
$mySession->destroy();
The Session::set
method only takes string
as a second parameter. You MUST
convert everything you want to store in your sessions to string
, e.g. using
PHP's built-in serialize()
, or json_encode()
.
In order to modify cookie options, a CookieOptions
object can be used as the
parameter to the Cookie
constructor, e.g.:
$myCookie = new fkooman\SeCookie\Cookie(
fkooman\SeCookie\CookieOptions::init()->withSameSiteStrict()
);
You can use the following methods on CookieOptions
:
withPath(string)
- restrict the cookie to the provided path. The default
restricts the cookie to the URL path that issues the cookie;withMaxAge(int)
- specify the maximum lifetime of the cookie in seconds;withSameSiteNone()
- only use this if you need to allow cross domain POST
responses, e.g. when implementing a SAML SPwithSameSiteLax()
- only send the cookie for cross domain "top level
navigation", not for methods that can change state on the server, e.g. POST
requests;withSameSiteStrict()
- do not send any cookie for any cross domain requestwithoutSecure()
- omits the Secure
flag from the cookie options, this
is ONLY meant for development!NOTE: CookieOptions
is immutable. This means that when you call withX()
or withoutX()
you get a copy of the current CookieOptions
with the new
value set. It will NOT modify the existing object!
In order to modify session options, a SessionOptions
object can be used as
the first parameter to the Session
constructor. If you also want to modify
the CookieOptions
, specify a CookieOptions
object as the second parameter,
e.g.:
$mySession = new fkooman\SeCookie\Session(
fkooman\SeCookie\SessionOptions::init()->withName('MYSID'),
fkooman\SeCookie\CookieOptions::init()->withSameSiteStrict()
);
You can use the following methods on SessionOptions
:
withName(string)
- specify the session name. The default is SID
;withExpiresIn(DateInterval)
- specify the time a session is valid, on the
server,. The default is new DateInterval('PT30M')
, which is, 30 minutes;NOTE: SessionOptions
is immutable. This means that when you call withX()
or withoutX()
you get a copy of the current SessionOptions
with the new
value set. It will NOT modify the existing object!
The third parameter is the SessionStorageInterface
. You can specify the
storage backend as shown below.
By creating multiple Session
objects, you can have multiple parallel
sessions.
The file backend is the simplest to use and the default. By default it will use the same directory as PHP's built-in session storage as a place to store the session data. You can optionally specify your own path as well.
Example:
$sessionStorage = new fkooman\SeCookie\FileSessionStorage();
In order to periodically remove expired sessions from the disk, you can use the
following command, or for example run it daily from cron(8)
.
On CentOS/Fedora:
$ sudo /usr/bin/find /var/lib/php/session -ignore_readdir_race -type f -name "sses_6_*" -mtime +0 -delete
On Debian/Ubuntu:
$ sudo /usr/bin/find /var/lib/php/sessions -ignore_readdir_race -type f -name "sses_6_*" -mtime +0 -delete
In case you want to use load balancing for your application you can use memcached. By deploying this on multiple machines you can create redundancy.
Session data is written to all memcache servers. Reading session data will be attempted from all servers, but be satisfied with the first response. This allows you to add/remove memcache servers. As long as one stays up, the sessions will remain valid.
NOTE: there is currently NO synchronization between memcache servers, so if you add a new one, or reboot a server it will receive new sessions, but will never know about the "old" ones. If this is important you could write your own "sync" mechanism. If you do, please contribute it :-)
$sessionStorage = new fkooman\SeCookie\MemcacheSessionStorage(
[
'cache1.example.org:11211',
'cache2.example.org:11211',
]
);
The database backend SHOULD not be used, as it is slow, especially when using databases over the network.
If you design your applications properly, at least session data is only read from the database and not written (back) at every page load as only modified session data is written to storage again.
$sessionStorage = new fkooman\SeCookie\PdoSessionStorage(
new PDO('sqlite:///path/to/db.sqlite')
);
// to initialize the database
$sessionStorage->init();
Early versions of version 6 of the library used exclusively the PHP functions
serialize()
and unserialize()
to serialize the session data. This is only
secure if the session data can't be manipulated outside of the application
using this library. In version >= 6.2 there is the option to also serialize
to JSON. This will be the default (and only option) in version 7 of the
library.
For example, to use the JSON serialization with MemcacheSessionStorage
:
$sessionStorage = new fkooman\SeCookie\MemcacheSessionStorage(
[
'cache1.example.org:11211',
'cache2.example.org:11211',
],
new fkooman\SeCookie\JsonSerializer()
);
It is HIGLY RECOMMENDED! to always use JsonSerializer()
!
Unit tests are included. You can easily run them:
$ vendor/bin/put
Please read the following resources so you have a good understanding of sessions and whether this library is suitable for your application or you are better of using any of the other available libraries or perhaps native PHP sessions.
MIT.
You can contact me with any questions or issues regarding this project. Drop me a line at fkooman@tuxed.net.
If you want to (responsibly) disclose a security issue you can also use the
PGP key with key ID 9C5EDD645A571EB2
and fingerprint
6237 BAF1 418A 907D AA98 EAA7 9C5E DD64 5A57 1EB2
.