dauerhafter Login / Cookie oder Session Lifetime?

versuch13

Erfahrenes Mitglied
Ich möchte einen dauerhaften Login (7 Tage) realisieren. Nun frage ich mich was die beste und vor allem sicherste Methode dafür ist?

Momentan werden eingeloggte User an einer Session erkannt. Daher habe setze ich nun beim Login einen Cookie, besucht der User die Seite und es ist ein Cookie gestetzt aber keine Session so wird diese gestaret.

Session Einstellungen
HTML:
    ini_set('session.use_trans_sid', 0);
    ini_set('session.use_cookies', 1);

Beim einloggen:

zu erste Datenbankabfrage und vergleich der Formulardaten mit den Daten der Datenbank und dann werden Sessions und Cookies gesetzt.

PHP:
                session_regenerate_id(true);
                $_SESSION['logged_in'] = true;
                $_SESSION['user'] = fct_text($row['name']);
                $_SESSION['userid'] = (int) $row['id'];
                $_SESSION['rights'] = (int) $row['rights'];
                $sessionid = session_id();
                $query =     "INSERT INTO sessions (uid, sessionid, savetime) VALUES (".$row['id'].", '".$sessionid."', NOW())
                            ON DUPLICATE KEY UPDATE savetime = NOW(), sessionid = '".$sessionid."'
                            ";        
                $result = mysql_query($query) OR die(mysql_error());
                setcookie('UID', (int) $row['id'], time()+3600*24*7);
                setcookie('SID', $sessionid, time()+3600*24*7);

Kommt der User nun wieder und es besteht ein Cookie:
PHP:
    if(isset($_COOKIE['SID']) AND !isset($_SESSION['logged_in'])) {
        $sql =    "SELECT
                    a.`id`,
                    a.`name`,
                    a.`rights`,
                    b.`sessionid`
                FROM
                    `user` as `a`
                INNER JOIN
                    `sessions` as `b`
                ON 
                    a.`id` = b.`uid`
                WHERE
                    a.`id` = ".(int) $_COOKIE['UID']."
                    AND DATEDIFF(NOW(), b.`savetime`) <= 7
                ";
        $result = mysql_query($sql) OR die(mysql_error());
        $row = mysql_fetch_assoc($result);
        if($row['sessionid'] == $_COOKIE['SID']) {
            $_SESSION['logged_in'] = true;
            $_SESSION['user'] = fct_text($row['name']);
            $_SESSION['userid'] = (int) $row['id'];
            $_SESSION['rights'] = $row['rights'];         
        }
    }

ich habe mir gedacht ich speicher zusätzlich etwas in der Datenbank um den User nochmals zu identifizieren, ich speichere die SessionID beim einloggen in der Datenbank und in einem dauerhaften Cookie und vergleiche diese Daten beim erneuten setzen der Session. Macht dass so überhaupt Sinn? Eher nicht oder? Denn gelangt jemand an die Cookie Daten so erhält er zutritt.

Des weiteren, ich habe gesehen dass das Loginsystem von Drupal mit session.cookie_lifetime die Session Dauer auf knapp vier Wochen setzt, aber auch dort werden zusätzliche Daten in der Datenbank abgelegt nur ganz durchsteigen tue ich da nicht. Wäre session.cookie_lifetime zu erhöhen auch eine Möglichkeit?

Worauf ich also hinaus will ist hoffentlich klar, wie sichere ich das System ab?
 
Das Thema ist weit verbreitet, bevor ich das Thema eröffnet habe habe ich auch hier schon einige Themen gefunden die sich damti befassen und auch reichlich im Netz recherchiert, aber eine zufriedenstellende Lösung konnte ich einfach nicht finden.

Ist das ein so schweres Thema? Wie ist es wenn jemand die Cookie Daten in die Finger bkeommt, kann man dann überhaupt irgendwie verhindern dass sich die Person einen fremden Account vornimmt?
 
Die Lebenszeit des Sitzungscookies zu verlängern halte ich nur dann für sinnvoll wenn auch gleichzeitig die Lebenszeit der Sitzung selbst, also der serverseitig gespeicherten Daten, verlängert wird. Doch das wäre keine gute Idee, da so schnell der Speicherplatz von möglicherweise gar nicht mehr benötigten Sitzungsdaten aufgefressen würde.
Besser, finde ich, ist es da neben dem Sitzungscookie einen weiteren Cookie einzusetzen, mit dem die Identifizierung des Benutzers durchgeführt wird. Als Wert schlage ich die Benutzer-ID sowie ein paar weitere Informationen über den Benutzer (beispielsweise digitaler Fingerabdruck) in verschlüsselter Form vor.
Alternativ zur Verschlüsselung kannst du auch ein Cookie mit den Werten und einen zusätzlichen Cookie zur Authentifizierung des Cookies mit den Werten einsetzen.
 
Die Lebenszeit des Sitzungscookies zu verlängern halte ich nur dann für sinnvoll wenn auch gleichzeitig die Lebenszeit der Sitzung selbst, also der serverseitig gespeicherten Daten, verlängert wird. Doch das wäre keine gute Idee, da so schnell der Speicherplatz von möglicherweise gar nicht mehr benötigten Sitzungsdaten aufgefressen würde.

Das habe ich schon vermutet, ok, danke. Aber dazu trotzdem auch noch eine kurze Frage. Wenn man die Lebenszeit des Sessioncookies auf sagen wir mal 24 Std. setzen würde, was zum Beispiel Sinn machen würde bei einer Seite welche täglich meist die selben Nutzer hat, so würde für die User die täglich vorbei kommen der Login dauerhaft erhalten bleiben und wenn man die SessionId bei jedem Seitenaufruf erneuert dann wäre das doch eine ziemliche sichere Methode einen dauerhaften Login zu realisieren oder? Würde denn bei einer so kurzen Lebenszeit der Server auch stark belastet werden oder könnte man diese Möglichkeit in Erwägung ziehen? Und bleiben die Session Variablen auch in jedem Fall über 24 Stunden erhalten?

Alternativ zur Verschlüsselung kannst du auch ein Cookie mit den Werten und einen zusätzlichen Cookie zur Authentifizierung des Cookies mit den Werten einsetzen.

Das verstehe ich leider nicht, vllt kannst du darauf nochmal eingehen bitte?

Besser, finde ich, ist es da neben dem Sitzungscookie einen weiteren Cookie einzusetzen, mit dem die Identifizierung des Benutzers durchgeführt wird. Als Wert schlage ich die Benutzer-ID sowie ein paar weitere Informationen über den Benutzer (beispielsweise digitaler Fingerabdruck) in verschlüsselter Form vor.

In etwa so sieht das nun auch aus.

Beim absenden des Login Formulares.
PHP:
            $sql =     "SELECT
                        `id`, `name`, `password`, `rights`
                    FROM 
                        `user` 
                    WHERE
                        `name` = '". mysql_real_escape_string($_POST['user']) ."' AND `password` = '". mysql_real_escape_string(md5($_POST['password'])) ."' AND `flag` = 1 
                    ";
                            
            $result = mysql_query($sql) OR die(mysql_error());
                    
            if( !mysql_num_rows($result) ) {
                $msg .= "Login fehlgeschlagen. Ein Benutzer mit diesen Daten ist nicht vorhanden.<br />";
                $info .= 'Hast du deinen Usernamen oder Passwort vergeßen? Beantrage hier neue Zugangsdaten.';
            } else {
                $row = mysql_fetch_array($result);
                session_regenerate_id(true);
                $_SESSION['logged_in'] = true;
                $_SESSION['user'] = fct_text($row['name']);
                $_SESSION['userid'] = (int) $row['id'];
                $_SESSION['rights'] = (int) $row['rights'];
                $sessionid = session_id();
                $cookieLifetime = time()+3600*24*7;
                $hash = md5(session_id().$_SERVER['HTTP_USER_AGENT']);
                $query =     "INSERT INTO sessions (uid, sessionid, savetime) VALUES (".$row['id'].", '".$sessionid."', NOW())
                            ON DUPLICATE KEY UPDATE savetime = NOW(), sessionid = '".$sessionid."'
                            ";        
                $result = mysql_query($query) OR die(mysql_error());
                setcookie('UID', $row['id'], $cookieLifetime);
                setcookie('SID', $hash, $cookieLifetime);
            }
Beim widerkehrenden Nutzer mit gesetzten Cookies:
PHP:
    if(isset($_COOKIE['SID']) AND !isset($_SESSION['logged_in'])) {
    
        $sql =    "SELECT
                    a.`id`,
                    a.`name`,
                    a.`rights`,
                    b.`sessionid`
                FROM
                    `user` as `a`
                INNER JOIN
                    `sessions` as `b`
                ON 
                    a.`id` = b.`uid`
                WHERE
                    b.`uid` = ".(int) $_COOKIE['UID']."
                    AND DATEDIFF(NOW(), b.`savetime`) <= 7
                    AND a.`flag` = 1
                ";
        $result = mysql_query($sql) OR die(mysql_error());
        $row = mysql_fetch_assoc($result);
        if(md5($row['sessionid'].$_SERVER['HTTP_USER_AGENT']) == $_COOKIE['SID']) {
            $_SESSION['logged_in'] = true;
            $_SESSION['user'] = fct_text($row['name']);
            $_SESSION['userid'] = (int) $row['id'];
            $_SESSION['rights'] = $row['rights'];
        }
        
    }

Ich speichere also die reine Session Id in der Datenbank, und einen Cookie der aus der SessionId und dem HTTP_USER_AGENT in codierter Form besteht und vergleiche dann beim widerkehrenden Nutzer die SessionId aus der DB + HTTP_USER_AGENT in codierter Form mit dem Cookie. Durch die Verwendung des HTTP_USER_AGENT ergibt sich in meinen Augen ein kleiner Pluspunkt sollten Cookie Daten in fremde Hände kommen. Aber wenn jemand an die Cookie Daten ran käme, dann wäre es trotzdem nicht wirklich ganz sicher.

Ich achte schon sehr stark darauf alle XSS Lücken zu schließen und denke von der Seite aus ist auch alles soweit sicher, aber man kann ja immer mal eine Kleinigkeit übersehen und das größte Problem für mich liegt nur darin dass ich nicht weiß welche weiteren/ob überhaupt weitere Möglichkeiten bestehen wie jemand an die Cookie Daten kommen könnte. Klar, wenn jemand seine Cookie Daten selbst veröffentlicht, aber wenn theoretisch alle XSS Lücken geschlossen sind, besteht dann überhaupt noch Grund zur Sorge?

Vielen Dank und Grüße
 
Zuletzt bearbeitet:
Kann mir vielleicht noch jemand die Fragen aus meinem letzten Post beantworten? Ich suche mich dumm und dämlich und finde irgendwie nichts anständiges zu dem Thema. Aber es gibt so viele Webseiten die einen dauerhaften Login ermöglichen, es kann doch nicht sein dass dort überall die Sicherheit vernachlässigt wird oder? Vielen Dank, Grüße
 
So in der Art hab ich das...
Zusätzlich wird IP gesichert, sicher is sicher... ^^

PHP:
// Prüfen, ob ein Autologin des Users stattfinden muss
if(isset($_COOKIE['Autologin']) AND !isset($_SESSION['UserID'])){
$sql = "SELECT
ID
FROM
User
WHERE
Autologin = '".mysql_real_escape_string($_COOKIE['Autologin'])."'
";
$result = mysql_query($sql) OR die("<pre>\n".$sql."</pre>\n".mysql_error());
$row = mysql_fetch_assoc($result);
if(mysql_num_rows($result) == 1)
doLogin($row['ID'], '1');
}

// Online Status der User aktualisieren
if(isset($_SESSION['UserID'])){
$sql = "UPDATE
User
SET
Letzte_Aktion = '".time()."'
WHERE
ID = '".$_SESSION['UserID']."'
";
mysql_query($sql) OR die("<pre>\n".$sql."</pre>\n".mysql_error());
}

// User ohne Autologin ausloggen
$sql = "UPDATE
User
SET
SessionID = NULL,
Autologin = NULL,
IP = NULL
WHERE
'".(time()-(60*30))."' > Letzte_Aktion AND
Autologin IS NULL
";
mysql_query($sql) OR die("<pre>\n".$sql."</pre>\n".mysql_error());

// Kontrollieren, ob ein automatisch ausgeloggter User noch eine gültige Session besitzt
if(isset($_SESSION['UserID'])){
$sql = "SELECT
SessionID
FROM
User
WHERE
ID = '".$_SESSION['UserID']."'
";
$result = mysql_query($sql) OR die("<pre>\n".$sql."</pre>\n".mysql_error());
$row = mysql_fetch_assoc($result);
if(!$row['SessionID']){
$_SESSION = array();
session_destroy();
}
}
 
Und was enthält $_COOKIE['Autologin']?

Aber auch hier, bekommt ein wer den Cookie in die Hand so kann er sich
ohne weiteres einloggen oder nicht? Da bin ich mit dem vergleich des
UserAgents noch mehr auf der sicheren Seite oder?
 
Der Cookie wird bei login gesetzt...
PHP:
// Falls der Nickname und das Passwort übereinstimmen..
$sql = "SELECT
ID
FROM
User
WHERE
Nickname = '".mysql_real_escape_string(trim($_POST['Nickname']))."' AND
Passwort = '".md5(trim($_POST['Passwort']))."'
";
$result = mysql_query($sql) OR die("<pre>\n".$sql."</pre>\n".mysql_error());
// wird die ID des Users geholt und der User damit eingeloggt
$row = mysql_fetch_assoc($result);
// Prüft, ob wirklich genau ein Datensatz gefunden wurde
if (mysql_num_rows($result)==1){
doLogin($row['ID'], isset($_POST['Autologin']));
}
////Die Login Funktion
// Loggt einen User ein, ..
function doLogin($ID, $Autologin=false)
{
// .. indem die aktuelle Session ID in der Datenbank gespeichert wird
$sql = "UPDATE
User
SET
SessionID = '".mysql_real_escape_string(session_id())."',
Autologin = NULL,
IP = '".$_SERVER['REMOTE_ADDR']."',
Letzte_Aktion = '".mysql_real_escape_string(time())."',
Letzter_Login = '".mysql_real_escape_string(time())."'
WHERE
ID = '".$ID."'
";
mysql_query($sql) OR die("<pre>\n".$sql."</pre>\n".mysql_error());
// Wenn 'eingeloggt bleiben' aktiviert wurde
if($Autologin){
// Zufallscode erzeugen
$part_one = substr(time()-rand(100, 100000),5,10);
$part_two = substr(time()-rand(100, 100000),-5);
$Login_ID = md5($part_one.$part_two);
// Code im Cookie speichern, 10 Jahre dürfte genügen
setcookie("Autologin", $Login_ID, time()+60*60*24*365*10);
$sql = "UPDATE
User
SET
Autologin = '".$Login_ID."'
WHERE
ID = '".$ID."'
";
mysql_query($sql) OR die("<pre>\n".$sql."</pre>\n".mysql_error());
}
function getRights()
{
$rights = array();
// .. indem die Rechte eines User aus der Datenbank ausgewählt werden..
if(isset($_SESSION['UserID'])){
$sql = "SELECT
Recht
FROM
User_Rechte
WHERE
UserID = '".$_SESSION['UserID']."'
";
$result = mysql_query($sql) OR die ("<pre>\n".$sql."</pre>\n".mysql_error());
// .. und als array zurückgegeben werden
while($row = mysql_fetch_assoc($result))
$rights[] = $row['Recht'];
}
return $rights;
}
// Daten des Users in der Session speichern
$sql = "SELECT
Nickname
FROM
User
WHERE
ID = '".$ID."'
";
$result = mysql_query($sql) OR die("<pre>\n".$sql."</pre>\n".mysql_error());

$row = mysql_fetch_assoc($result);
$_SESSION['UserID'] = $ID;
$_SESSION['Nickname'] = $row['Nickname'];
// Rechte in der Session speichern
$_SESSION['Rechte'] = getRights();
}

Überprüfen und abfragen zum sicher gehen kannste theretisch alle erreichbaren User-Infos...
Bleibt ja jedem selbst überlassen, wie genau er sein will...

Mit bestimmter IP hält der maximal 24Std...
Dann musste die aktualisieren, indem du eine weitere Variable beim User hast, der ihn Identifiziert, also den Cookie...
 
Du identifizierst den User also nur anhand er IP Adresse? Das ist eigentlich keine gute Idee oder sehe ich das falsch? Denn es ist möglich dass mehrere User die selbe IP Adresse hätten, oder dass ihre IP Adresse von Request zu Request verändert wird.
 
Zurück