Php Sessies

Inhoud

Problemen met PHP sessies

PHP bevat een standaard hulpstuk voor het gebruik van sessies (zie http://nl2.php.net/session voor meer informatie). Deze session-handler heeft een aantal fundamentele problemen, door de manier waarop sessies worden opgeslagen. PHP sessies zijn :

  • Onbetrouwbaar: er is geen enkele garantie dat de sessie voor een bepaalde tijd bestaat. Er zijn verschillende oorzaken waardoor een sessie eerder, of juist heel veel later kan verlopen dan u verwacht. Zo kunnen de bezoekers van uw site plotseling worden uitgelogd, of kunnen ze juist na 3 maanden gewoon met dezelfde sessie inloggen.
  • Onveilig: andere gebruikers van dezelfde server, kunnen relatief eenvoudig uw sessie data bekijken, of uw sessies laten verlopen. Sla dus nooit gevoelige informatie in PHP sessies op!

Oorzaak

Het probleem onstaat doordat sessie-data lokaal op een lokatie voor tijdelijke bestanden wordt opgeslagen. Doordat PHP standaard met de rechten van de webserver draait, kan PHP niet goed onderscheid maken tussen sessies van de ene en de andere site. Daarnaast is het, door het lokale karakter van de sessies, niet goed mogelijk voor een website om op meerdere servers te draaien. Stel dat er een webserver uitvalt, dan is het niet mogelijk om de sessies mee te nemen naar een reserve server. Dit hebben wij opgelost door ervoor te zorgen dat u altijd wordt geholpen door één en dezelfde server, binnen een timeout van 1440 seconden. Deze timeout is, niet geheel ontoevallig, gelijk aan de standaard timeout van PHP sessies. Gebruikt u een langere timeout, dan zullen de lokale sessies niet goed meer werken.

Dit wordt mogelijk verbeterd in een volgende versie van PHP, maar gelukkig is er tot die tijd een bruikbaar alternatief. Mocht u er toch voor kiezen om de standaard sessiehandler van PHP te gebruiken, dan is het raadzaam om onze PHP Sessions Policy even door te lezen.

Alternatief

Maak gebruik van de custom session handler in PHP! De truc is om gebruik te blijven maken van de handige PHP sessie-beheersfuncties, maar de eigenlijke sessies zelf in een database op te slaan. Om de database tabel te maken kunt u bijvoorbeeld de volgende query gebruiken:

CREATE TABLE `session` (
 `sess_id` varchar(40) NOT NULL,
 `changed` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
 `vars` text NOT NULL,
 PRIMARY KEY(`sess_id`)
);

Hieronder staat een voorbeeld van een php session handler:

<?php
 
/*
 +-----------------------------------------------------------------------+
 | voorbeeld php session handler                                         |
 | gebaseeerd op de sessie handlers van Roundcube                        |
 +-----------------------------------------------------------------------+
 
*/
 
function sess_open($save_path, $session_name)
{
: global $DB;
: $DB = new mysqli('host', 'gebruiker', 'wachtwoord', 'database');
: return TRUE;
}
 
function sess_close()
{
: return TRUE;
}
 
// read session data
function sess_read($key)
{
: global $DB;
: $stmt = $DB->prepare("SELECT vars FROM session WHERE  sess_id=?");
: $stmt->bind_param("s",$key);
: $stmt->bind_result($vars);
: if ($stmt->execute() && $stmt->fetch())
: {
	$stmt->close();
	return $vars;
: }
: $stmt->close();
: return FALSE;
}
 
// save session data
function sess_write($key, $vars)
{
: global $DB;
: $stmt = $DB->prepare("SELECT 1 FROM session WHERE sess_id = ?");
: $stmt->bind_param("s",$key);
: $stmt->bind_result($result);
 
: if ($stmt->execute() && $stmt->fetch())
: {
	$stmt->close();
	$stmt = $DB->prepare("UPDATE session SET vars=?, changed=NOW() WHERE  sess_id = ?");
	$stmt->bind_param("ss", $vars, $key);
	$stmt->execute();
	$stmt->close();
: }
: else
: {
	$stmt->close();
	$stmt = $DB->prepare("INSERT INTO session (sess_id, vars, changed) VALUES (?, ?, NOW())");
	$stmt->bind_param("ss", $key, $vars);
	$stmt->execute();
	$stmt->close();
: }
 
: return TRUE;
}
 
 
// handler for session_destroy()
function sess_destroy($key)
{
: global $DB;
 
: $stmt = $DB->prepare("DELETE FROM session WHERE sess_id=?");
: $stmt->bind_param("s", $key);
: $stmt->execute();
: $stmt->close();
: return TRUE;
}
 
// garbage collecting function
function sess_gc($maxlifetime)
{
: global $DB;
 
: // get all expired sessions
: $stmt = $DB->prepare("DELETE FROM session WHERE now() - changed  > ?");
: $stmt->bind_param("i", $maxlifetime);
: $stmt->execute();
: $stmt->close();
: return TRUE;
}
 
 
// set custom functions for PHP session management
session_set_save_handler('sess_open', 'sess_close', 'sess_read', 'sess_write', 'sess_destroy', 'sess_gc');
register_shutdown_function('session_write_close');
?>

Toelichting:

  • We gebruiken hier de mysqli functies van PHP
  • De database wordt geopend in de sess_open() functie. Als u al een database handle hebt, kunt u die natuurlijk gebruiken.
  • De regel register_shutdown_function('session_write_close'); is nodig omdat de $DB variabele anders vernietigd is voordat de sessie opgeslagen wordt. Zie ook PHP 5 sessions in mysql database with PDO db objects
  • In Joomla 1.5 kunt u een database session handler instellen in Global Configuration op het tabblad System.

Mocht u nog vragen hebben, neem dan svp contact op met support@byte.nl.

Sommige pagina's geven permission denied meldingen

Dit kan verschillende oorzaken hebben. Als u bijvoorbeeld een bestand zonder .php extensie in php probeert uit te voeren met een .htaccess regel als

<Files webshop>
 [[Force Type]] application/x-httpd-php
</Files>

zal dit bestand in Safe Mode draaien, terwijl de rest van de site in CGI mode draait. Als het CGI script een sessie aanmaakt, kan het Safe Mode script dit sessie bestand niet openen. U kunt dit bijvoorbeeld oplossen door deze regel aan te passen:

<Files webshop>
 [[Force Type]] application/cgi-php5
</Files>
Nog niemand heeft een waardering kenbaar gemaakt voor dit artikel
 You need to enable JavaScript to vote

We proberen de kwaliteit van onze kennisbank voortdurend te verbeteren.
Geef de informatie op deze pagina een waardering met de slider hierboven.