 | |
04.06.2006, 17:16
| Nach oben
#1 | | Benjamin Klaile
Registriert seit: 02.12.2004 Ort: Remagen
Beiträge: 4.471
| SessionManagement: PHP-Sessions oder eigene Session-Klasse?
Hallo,
aus aktuellen Anlass frage ich mich gerade, wo der Vorteil von einem eigenen gegenüber dem PHP-internen SessionManagement liegt und wie man dies am besten umsetzt, falls überhaupt sinnvoll.
Das Simple Machines Forum nutzt dies ja. Dort werden afaik die Sessiondaten in der Datenbank gespeichert!?
Ich persönlich sehe aber gar keinen Anhaltspunkt, warum das denn überhaupt besser sein sollte. 
Geht es dort um Performance-/Sicherheitsaspekte oder nur um eine Abstraktion mehr im Gesamtsystem?
Würde mich über eine Diskussion diesbzgl. freuen.
Danke für Eure rege Teilnahme.
Grüße, Ben.
|
| |
04.06.2006, 17:35
| Nach oben
#2 | | Lutz
Registriert seit: 14.08.2005 Ort: Nienburg / Weser
Beiträge: 684
|
Ich persönlich sehe da wenn überhaupt eigentlich auch nur den Sinn drin, dass man bei einem eigenen System dieses besser in eine reine OOP-Umgebung bringen kann, aber das wars dann auch schon!? Ich kann mir nicht vorstellen, dass eine Funktion, die in PHP geschrieben wurde schneller sein soll, als eine Funktion, die in C geschrieben wurde und direkt in PHP kompiliert ist!?
__________________ Paradox ist, wenn jemand für seinen Alkoholkonsum geradestehen soll |
| |
04.06.2006, 17:37
| Nach oben
#3 | | Benjamin Klaile
Registriert seit: 02.12.2004 Ort: Remagen
Beiträge: 4.471
|
Jou, das glaube ich auch eher nicht. Sagen wir mal so .. ich wäre überrascht.
Bzgl. Zitat: |
Zitat von MrNiceGuy dass man bei einem eigenen System dieses besser in eine reine OOP-Umgebung bringen kann | Wie würdest du das dann umsetzen, damit es auch einen Sinn ergibt?
Kleinen Codeschnipsel parat?
|
| |
04.06.2006, 17:41
| Nach oben
#4 | | Gast |
Es geht nur um Sicherheitsaspekte. Eine weitere Abstraktionsschicht hast du nicht weil trotzdem über $_SESSION ganz normal zugegriffen wird.
Zur Sicherheit: Wenn deine Anwendung die einzige auf dem Server ist, so hilft dir das Sessionhandling über eine DB nichts. Da allerdings die meisten E-Commerce, CM Systeme auf Shared Hosts laufen, kann jeder User der Zugriff auf den Server hat die Sessiondaten und IDs auslesen. Sessions werden nämlich einfach in einem temporären Verzeichnis als Dateien am Server abgelegt. Durch die Einstellung session.save_path bekommt man den Pfad zum Verzeichnis. Jetzt kann man sich ein einfachs Script schreiben, dass dieses Verzeichnis öffnet die Dateien ausliest und ausliest. Damit ist es ein leichtes eine andere Anwendung am gleichen Server zu knacken.
Ein Script könnte so in etwa aussehen: PHP-Code: session_start (); $handle = dir (ini_get ("session.save_path")); while ($file = $handle->read ()) {
if (substr ($file, 0,5)=="sess_") { ... ...
} }
Schreibt man jetzt allerdings die Daten in eine Datenbank, so sind darin sicher verwahrt, weil die anderen Nutzer ja keinen Username/Passwort dafür haben.
EDIT: Zitat: |
dass man bei einem eigenen System dieses besser in eine reine OOP-Umgebung bringen kann
| Wie denn? session_start() funktioniert dann ja nicht!
Für ein eigenes Sessionhandling verwendet man session_set_save_handler (...), weil sich da praktisch PHP um alles kümmert und es schnell und effizient ist.
jay
Geändert von Jay (04.06.2006 um 17:46 Uhr).
| |
| |
04.06.2006, 17:42
| Nach oben
#5 | | Lutz
Registriert seit: 14.08.2005 Ort: Nienburg / Weser
Beiträge: 684
|
Ich sagte nicht, dass ich das habe, ich sagte, dass es das einzige wäre, was in meinen Augen Sinn machen WÜRDE, man beachte den Konjunktiv
__________________ Paradox ist, wenn jemand für seinen Alkoholkonsum geradestehen soll |
| |
04.06.2006, 17:47
| Nach oben
#6 | | Benjamin Klaile
Registriert seit: 02.12.2004 Ort: Remagen
Beiträge: 4.471
| Zitat: |
Zitat von Jay Es geht nur um Sicherheitsaspekte. Eine weitere Abstraktionsschicht hast du nicht weil trotzdem über $_SESSION ganz normal zugegriffen wird. | Abstraktion war auch das falsche Wort. Wollte eigentlich Wrapper schreiben. Zitat: |
Zitat von Jay kann jeder User der Zugriff auf den Server hat die Sessiondaten und IDs auslesen. Sessions werden nämlich einfach in einem temporären Verzeichnis als Dateien am Server abgelegt. Durch die Einstellung session.save_path bekommt man den Pfad zum Verzeichnis. Jetzt kann man sich ein einfachs Script schreiben, dass dieses Verzeichnis öffnet die Dateien ausliest und ausliest. Damit ist es ein leichtes eine andere Anwendung am gleichen Server zu knacken. | Kann man nicht alternativ einfach einen eigenen session.save_path setzen? http://de3.php.net/manual/en/functio...-save-path.php
@MrNiceGuy: |
| |
04.06.2006, 17:50
| Nach oben
#7 | | Gast | Zitat: |
Kann man nicht alternativ einfach einen eigenen session.save_path setzen?
| Dann liegt wieder alles am Filesystem und kann ausgelesen werden, außerdem musst du mal die entsprechenden Rechte besitzen, diese ini einstellung setzen zu dürfen und du brauchst ein entsprechendes schreibbares Verzeichnis, welches du dir auch nicht so einfach anlegen darfst.
Jay
| |
| |
04.06.2006, 17:55
| Nach oben
#8 | | Benjamin Klaile
Registriert seit: 02.12.2004 Ort: Remagen
Beiträge: 4.471
|
Hm, okay.
Hat eventuell jemand mal ein wenig Beispielcode bzw. kann mir erklären, wie man dann am geschicktesten solch einen Wrapper schreibt?
|
| |
04.06.2006, 17:59
| Nach oben
#9 | | Lutz
Registriert seit: 14.08.2005 Ort: Nienburg / Weser
Beiträge: 684
|
Hmm... Sehr interessant, da hatte ich noch garnicht drüber nachgedacht!? Aber bei meinem Webserver ist es zum Beispiel so, dass jede Domain seinen eigenen Benutzer hat, ich weiß allerdings gerade nicht, wie die Session-Datei im /tmp aussieht, könnte ja sein, dass die sowieso nur lese-rechte auf den Benutzer hat!? Denn sonst könnte man ja auch, wie du es gerade sagtest, Jay, einfach auf die Scripte selber zugreifen und dann hilft dir auch das Schreiben in die DB nicht mehr!?
EDIT: @ben: Die Funktionen serialize() und das Pendant unserialize() sollten die helfen.
__________________ Paradox ist, wenn jemand für seinen Alkoholkonsum geradestehen soll |
| |
04.06.2006, 18:03
| Nach oben
#10 | | Gast | Zitat: |
EDIT: @ben: Die Funktionen serialize() und das Pendant unserialize() sollten die helfen.
| session_decode ist wohl besser.
@Ben http://at.php.net/session_set_save_handler
Da ist ein Beispiel angeführt. Das verwendet wegen Einfachheit Dateien. Für eine DB müsstest du halt anstatt dateien zu schreiben und zu löschen SQL Queries verwenden
EDIT:
Zur Datei (ganz überlesen 
Name: sess_sessionid
Inhalt dürfe so in etwa aussehen wenn $_SESSION['asdf'] auf "jklö" gesetzt ist:
asdf|s:4:"jklö";
Würde man das serialisieren, dann würde das so aussehen
{s:4:"asdf";s:4:"jklö";}
Geändert von Jay (04.06.2006 um 18:12 Uhr).
| |
| |
04.06.2006, 19:26
| Nach oben
#11 | | Benjamin Klaile
Registriert seit: 02.12.2004 Ort: Remagen
Beiträge: 4.471
|
Ich habe soeben gemerkt, dass in meinem neuen Buch ausgiebig auf dieses Thema eingegangen wird.
Ich werde mich da also einmal einarbeiten.
|
| |
04.06.2006, 19:49
| Nach oben
#12 | | Neuer Benutzer
Registriert seit: 20.03.2006
Beiträge: 5
|
Hier ein simples, selbsterklärendes Session Handler System. PHP-Code: <?php
session_set_save_handler('_open', '_close', '_read', '_write', '_destroy', '_clean');
function _open() { global $_sess_db;
$db_user = $_SERVER['DB_USER']; $db_pass = $_SERVER['DB_PASS']; $db_host = 'localhost'; if ($_sess_db = mysql_connect($db_host, $db_user, $db_pass)) { return mysql_select_db('sessions', $_sess_db); } return FALSE; }
function _close() { global $_sess_db; return mysql_close($_sess_db); }
function _read($id) { global $_sess_db;
$id = mysql_real_escape_string($id);
$sql = "SELECT data FROM sessions WHERE id = '$id'";
if ($result = mysql_query($sql, $_sess_db)) { if (mysql_num_rows($result)) { $record = mysql_fetch_assoc($result);
return $record['data']; } }
return ''; }
function _write($id, $data) { global $_sess_db;
$access = time();
$id = mysql_real_escape_string($id); $access = mysql_real_escape_string($access); $data = mysql_real_escape_string($data);
$sql = "REPLACE INTO sessions VALUES ('$id', '$access', '$data')";
return mysql_query($sql, $_sess_db); }
function _destroy($id) { global $_sess_db; $id = mysql_real_escape_string($id);
$sql = "DELETE FROM sessions WHERE id = '$id'";
return mysql_query($sql, $_sess_db); }
function _clean($max) { global $_sess_db; $old = time() - $max; $old = mysql_real_escape_string($old);
$sql = "DELETE FROM sessions WHERE access < '$old'";
return mysql_query($sql, $_sess_db); }
?> |
| |
05.06.2006, 03:33
| Nach oben
#13 | | Goldman.de
Registriert seit: 09.10.2005 Ort: Frankfurt am Main
Beiträge: 190
|
- wenn man volle Kontrolle über sein Sessionhandling haben will
- Sessionmanagement in Verbindung mit Usermanagement
( xml basierend )
als Ansatz:
session.lib.inc PHP-Code: <?php // {{{ Header /** * session.lib.inc * * powered by Department-X.de * @autor j.mueller@department-x.de */ // }}} error_reporting(E_ALL);
unset($_SESSION);
// }}} // {{{ _properties
$sname = 'sid';
$spath = $dir.'sdata/';
$ctimeout = time() + 60*60*24*365*10;
$srcurl = $_SERVER['REQUEST_URI'];
$checked = false;
define("COOKIE_PREFIX", "smg");
$_level = array(); $_level['developer'] = 50; $_level['sysadmin'] = 30; $_level['mandant'] = 10; $_level['guest'] = 1; $_level['freez'] = 0;
$_referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : 'unknow';
$_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'unknow';
require_once('XML/Tree.php'); $xml = new XML_Tree($dir.'xmldb/user.xml'); $$dir = $xml->getTreeFromFile();
for ($i =0; $i < count($$dir->children); $i +=1) { if (strlen($$dir->children[$i]->attributes['name'])) { $usr[$$dir->children[$i]->attributes['name']]['pass'] = $$dir->children[$i]->attributes['pass']; $usr[$$dir->children[$i]->attributes['name']]['level'] = $$dir->children[$i]->attributes['level']; $usr[$$dir->children[$i]->attributes['name']]['userid'] = $$dir->children[$i]->attributes['userid']; } }
/** is session true */
if (isset($_POST[$sname]) && !empty($_POST[$sname])) { $_SESSION[$sname] = $_POST[$sname]; } elseif (isset($_GET[$sname]) && !empty($_GET[$sname])) { $_SESSION[$sname] = $_GET[$sname]; } else { $_SESSION[$sname] = isset($_COOKIE[COOKIE_PREFIX.$sname]) ? $_COOKIE[COOKIE_PREFIX.$sname] : false; }
if (isset($_SESSION[$sname]) && strlen($_SESSION[$sname])) { $username = isset($_COOKIE[COOKIE_PREFIX.'username']) ? $_COOKIE[COOKIE_PREFIX.'username'] : false; $userpass = isset($_COOKIE[COOKIE_PREFIX.'userpass']) ? $_COOKIE[COOKIE_PREFIX.'userpass'] : false; if (true == $username && false == $userpass) { /** korrupt */ @unlink($spath.$_SESSION[$sname]); setcookie(COOKIE_PREFIX.$sname, '', (1 - $ctimeout), '/'); setcookie(COOKIE_PREFIX.'username', '', (1 - $ctimeout), '/'); setcookie(COOKIE_PREFIX.'userpass', '', (1 - $ctimeout), '/'); unset($_SESSION); header("location:$srcurl"); } if (true == $userpass && false == $username) { /** korrupt */ @unlink($spath.$_SESSION[$sname]); setcookie(COOKIE_PREFIX.$sname, '', (1 - $ctimeout), '/'); setcookie(COOKIE_PREFIX.'username', '', (1 - $ctimeout), '/'); setcookie(COOKIE_PREFIX.'userpass', '', (1 - $ctimeout), '/'); unset($_SESSION); header("location:$srcurl"); } if (true == $username && true == $userpass) { if (isset($usr[$username])) { if ($usr[$username]['pass'] == $userpass) { if (true == file_exists($spath.$_SESSION[$sname])) { $scontent = file_get_contents($spath.$_SESSION[$sname]); $_SESSION = unserialize($scontent); $_SESSION['laststamp'] = time(); } else { $_SESSION['username'] = $username; $_SESSION['userpass'] = $userpass; $_SESSION['userlevel'] = $usr[$username]['level']; $_SESSION['useragent'] = $_agent; $_SESSION['referer'] = $_referer; $_SESSION['laststamp'] = time(); $_SESSION['loggedin'] = true; } $checked = true; } else { /** korrupt */ @unlink($spath.$_SESSION[$sname]); setcookie(COOKIE_PREFIX.$sname, '', (1 - $ctimeout), '/'); setcookie(COOKIE_PREFIX.'username', '', (1 - $ctimeout), '/'); setcookie(COOKIE_PREFIX.'userpass', '', (1 - $ctimeout), '/'); unset($_SESSION); header("location:$srcurl"); } } else { /** korrupt */ @unlink($spath.$_SESSION[$sname]); setcookie(COOKIE_PREFIX.$sname, '', (1 - $ctimeout), '/'); setcookie(COOKIE_PREFIX.'username', '', (1 - $ctimeout), '/'); setcookie(COOKIE_PREFIX.'userpass', '', (1 - $ctimeout), '/'); unset($_SESSION); header("location:$srcurl"); } } if (false == $checked) { if (true == file_exists($spath.$_SESSION[$sname])) { $scontent = file_get_contents($spath.$_SESSION[$sname]); $_SESSION = unserialize($scontent); $_SESSION['laststamp'] = time(); } else { $_SESSION['username'] = 'Gast'; $_SESSION['userpass'] = ''; $_SESSION['userlevel'] = 1; $_SESSION['useragent'] = $_agent; $_SESSION['referer'] = $_referer; $_SESSION['laststamp'] = time(); $_SESSION['loggedin'] = false; } } } else { $_SESSION[$sname] = createNewSessionId(); setcookie(COOKIE_PREFIX.$sname, $_SESSION[$sname], $ctimeout, '/'); $_SESSION['username'] = 'Gast'; $_SESSION['userpass'] = ''; $_SESSION['userlevel'] = 1; $_SESSION['useragent'] = $_agent; $_SESSION['referer'] = $_referer; $_SESSION['laststamp'] = time(); $_SESSION['loggedin'] = false; }
$loginusername = isset($_POST['loginusername']) && strlen($_POST['loginusername']) ? $_POST['loginusername'] : false;
$loginuserpass = isset($_POST['loginuserpass']) && strlen($_POST['loginuserpass']) ? md5($_POST['loginuserpass']) : false;
if (isset($cmd) && 'logout' == $cmd) { $pidname = substr(md5($_SESSION['username']), 0, 5).'.pid'; @unlink($dir.'pidfiles/'.$pidname); @unlink( | |