PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PHP - Sessionmanagement


Harleckin
2003-09-08, 15:11:20
Zusammen mit einen Kollegen haben wir ein System zur Verwaltung von Berichtsheften geschrieben, funktioniert in der Produktivumgebung auch sehr gut.
(Benutzerverwaltung, Speicherung der BH´s in einer mysqldb, Ausgabe als PDF etc.)

Genauer genommen haben wir zwei grundsätzliche Probleme..

1.) Im Falle es loggen sich mehrerer Personen zur gleichen Zeit ein, kommt es zur Überschneidung von Session-ID´s. Dass heißt im genaueren es befinden sich zwei oder mehrere Personen im gleichen Profil und nutzen die gleiche Session-ID.

2.) Nach einer zufälligen Zeitspanne, wird die gültige Session-ID eines Benutzers zerstört.
Meine Vermutung stürzt sich auf die "php.ini".

Nase
2003-09-08, 16:34:26
Hast du denn Zugriff auf die php.ini? Wenn ja, dann schau einfach mal rein, unter dem Punkt [Session] findest du die Einstellungen.

Ansonsten wäre vielleicht noch an ein fehlerhaftes Script eurerseits zu denken.

Harleckin
2003-09-08, 16:48:19
Die "php.ini" hab ich mir in Ruhe angeschaut.
Docs gibt es ja herrliche [1] und [2], aber wirklich schlauer bin ich nicht geworden.

Dass es am Script liegt bezweifle ich stark.


[1] http://de.php.net/de/session
[2] http://de.php.net/manual/de/function.ini-set.php

Nase
2003-09-08, 16:54:11
Gibst du uns denn trotzdem einen kleinen Einblick in den Code, der die Session erstellt?

Harleckin
2003-09-08, 17:14:30
Wenn Interesse besteht, würde ich die Sourcen des Systems uppen. (GPL)
Bevor das große Raten los geht, wie/warum/wo/was gelöst wurde.


<?

include("./includes/config.php");

// Lasst die Spiele beginnen!
@session_start();

// Session aktiv, User-Object zurueckholen, Login-Vorgang wird hier fortgesetzt, quasi volleendet
if(isset($_SESSION['sess_obj']) && isset($_SESSION['locked'])) {
$user = unserialize($_SESSION['sess_obj']);
// Verzweigung in spezifische User-Module
switch ($user->status) {
case "0": header("Location: " . $server . "/trainee/index" . $ext); break; // Azubi
case "1": header("Location: " . $server . "/adm/index" . $ext); break; // Admin
case "2": header("Location: " . $server . "/mod/index" . $ext); break; // Moderator
default: break;
}
// Session nicht aktiv
} else {

@session_destroy(); // alte Sessions zerstoeren
$sid = random_md5(); // neue Session-ID-Variable
@session_id($sid); // Session-ID festlegen
@session_start(); // Session starten


// Login-Formular nicht gesendet
if(!isset($_REQUEST['login'])) {

// HTML-Header ziehen
get_header($server);

// Startseite mit Login-Formularen
?>
<form action="<? echo $_SERVER['PHP_SELF']; ?>" method="post">
<a href="register.php" accesskey="r"><u>R</u>egistrieren</a> | <a href="pwd_request.php" accesskey="v">Passwort <u>v</u>ergessen</a> | <a href="faq.php" acces
skey="f"><u>F</u>AQ</a>
<hr class="hr_login">
<table border="0">
<tr><td><u>K</u>ennung:</td></tr>
<tr><td><input type="text" name="login_id" accesskey="k" class="white"></td></tr>
<tr><td><u>P</u>asswort:</td></tr>
<tr><td><input type="password" name="password" accesskey="p" class="white"></td></tr>
<tr><td class="td_right"><input type="submit" name="login" value="login"></td></tr>
</table>
</form>
<?
// html-footer
get_footer($server, $ext);

// Login-Formular gesendet
} else {
if((empty($_POST['login_id'])) || (empty($_POST['password']))) {
global_error(1, $server, $ext); // Login-Daten fehlen
} else {
$login_id = ucwords($_POST['login_id']); // Login-ID in Grossbuchstaben wandeln
$password = md5($_POST['password']); // PWD-md5-Hash bilden fuer DB-Abgleich

// DB oeffnen
$db = new db;
$db->connect();

// Login-ID, PWD in DB pruefen, mit einigen User-Rueckgaben
$query = mysql_query("
SELECT login, password, status, id
FROM user
WHERE login = '$login_id' and password = '$password';")
or die(mysql_error());

$user_data = mysql_fetch_array($query, MYSQL_ASSOC); // Daten aus DB in Array speichern

// DB schliessen
$db->close();

if(empty($user_data)) { // Pruefen, ob DB-Abfrage Werte zurueckgegeben hat
global_error(2, $server, $ext); // Login-Daten falsch
} else {
$_SESSION['locked'] = md5($sid); // aus Session-ID-locked Variable anlegen, damit klar ist, Session aktiv!
switch ($user_data['status']) {
case "0": // Trainee
$trainee = new trainee; // Azubi Obj anlegen
$trainee->login($user_data['id']); // quasi einloggen
$trainee->get_preferences(); // Einstellungen laden
$_SESSION['sess_obj'] = serialize($trainee); // Object fuer Session-Transport serializieren
header("Location: http://" . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF']); // Sprung zum Hauptteil
break;
case "1": // Admin
$admin = new admin; // Admin Obj anlegen
$admin->login($user_data['id']); // quasi einloggen
$_SESSION['sess_obj'] = serialize($admin); // Obj fuer Session-Transport serializieren
header("Location: http://" . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF']); // Sprung zum Hauptteil
break;
case "2": // Moderator
$mod = new moderator; // Moderator Obj anlegen
$mod->login($user_data['id']); // quasi einloggen
$mod->get_preferences(); // Einstellungen laden, hier die Ausbildungszeitraeume
$_SESSION['sess_obj'] = serialize($mod); // Obj fuer Session-Transport serializieren
header("Location: http://" . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF']); // Sprung zum Hauptteil
break;
default: break;
}
}
}
} // if
}
?>

Nase
2003-09-08, 18:40:45
Hmmm, ok....

Also, für mich scheint das alles ziemlich umständlich. Ich habe in einem anderen Projekt das so gelöst:

Schritt 1:
Es wird überprüft, ob die notwendigen Benutzerdaten in der Session registriert sind und man nicht ausgeloggt ist

Schritt 2:
Wenn das Passwort, dass registriert ist, richtig ist, wird der HTML-Code erzeugt

Schritt 3:
Falls das Formular mit dem Benutzernamen und Passwort abgeschickt wurde, werden die eingegebenen Daten mit denen in der Datenbank überprüft. Falls richtig, werden die Daten registriert, andernfalls kommt eine Fehlermeldung

Schritt 4:
Der User soll ausgeloggt werden. Session wird zerstört.

Schritt 5:
Wenn keiner von den oben genannten Fällen eintritt, wird wiederum eine HTML-Seite eingebunden.


So habe ich das gelöst und es funktioniert wunderbar. Hast du denn mal ausprobiert, ob dein Script auch wirklich alles ausführt?

Ich bin mir an dieser Stelle

WHERE login = '$login_id' and password = '$password';")

nicht ganz sicher, ob das ; am Ende nichts ausmacht.

Harleckin
2003-09-08, 21:02:02
Original geschrieben von Nase
Schritt 1:
Es wird überprüft, ob die notwendigen Benutzerdaten in der Session registriert sind und man nicht ausgeloggt ist

Hab ich..

if((empty($_POST['login_id'])) || (empty($_POST['password']))) {


Schritt 2:
Wenn das Passwort, dass registriert ist, richtig ist, wird der HTML-Code erzeugt

Dafür steht ein Link zur entsprechender Seite..

<a href="register.php" accesskey="r"><u>R</u>egistrieren</a>


Schritt 3:
Falls das Formular mit dem Benutzernamen und Passwort abgeschickt wurde, werden die eingegebenen Daten mit denen in der Datenbank überprüft. Falls richtig, werden die Daten registriert, andernfalls kommt eine Fehlermeldung

Wir nehmen erstmal die Eingabe..

$login_id = ucwords($_POST['login_id']); // Login-ID in Grossbuchstaben wandeln

$password = md5($_POST['password']); // PWD-md5-Hash bilden fuer DB-Abgleich

Dann ziehen wir die Daten aus der DB und gleichen ab. Die generierte MD5-Prüfsumme aus der Eingabe wird mit der aus der DB verglichen! (PW steht natürlich als MD5-Hash in der DB)

Schritt 4:
Der User soll ausgeloggt werden. Session wird zerstört.


if(empty($user_data)) { // Pruefen, ob DB-Abfrage Werte zurueckgegeben hat

global_error(2, $server, $ext); // Login-Daten falsch


Schritt 5:
Wenn keiner von den oben genannten Fällen eintritt, wird wiederum eine HTML-Seite eingebunden.

Die wäre??

So habe ich das gelöst und es funktioniert wunderbar. Hast du denn mal ausprobiert, ob dein Script auch wirklich alles ausführt?

Das Script funktioniert bestens.

Ich bin mir an dieser Stelle

WHERE login = '$login_id' and password = '$password';")

nicht ganz sicher, ob das ; am Ende nichts ausmacht.
Das passt schon! Wie gesagt es werden MD5-Hashes verglichen.

Nase
2003-09-08, 21:08:49
Die Seite die in Schritt 5 eingebunden wird, ist einfach nur wieder das Login Formular, da keiner ohne die erforderlichen Berechtigungen diese Seite betreten darf.

Was dein Problem angeht, da kann ich dir z.Z. nicht weiterhelfen. Ich schaff es nicht wirklich, mich da reinzudenken. (Liegt bestimmt am Wetter ;) )

Harleckin
2003-09-08, 21:24:37
Kennst du eine gute Mailinglist bzw. Forum wo ich tiefergehendere Hilfe finden könnte?


MfG

Nase
2003-09-08, 21:32:36
Hmmm, so direkt würde ich sagen, schau einfach mal beim Hersteller von PHP in die Foren (http://www.zend.com/phorum/).

Harleckin
2003-09-10, 10:13:03
Wie sich herausstellt, läuft so manches anders wie es evt. sollte..

"session_cache_expire" springt zwischen drei Werten {3,60,180}Min. innerhalb einer Session. Obwohl der Wert vor der Initalisierung der Session auf "3" gesetzt wurde. :|

"session.cache_limiter" steht auf "nocache", woraufhin eigentlich "session_cache_expire" ignoriert wird.
Trotzdem wird die Session nach einer Weile zerstört.

Update:

"session_cache_expire" = 3
"session.cache_limiter" = private

..sollte dies nicht die Session nach drei Minuten zerstören? Tut es aber natürlich nicht.


http://de3.php.net/de/session