Wie lasse ich eine PHP-Sitzung nach 30 Minuten ablaufen?

1047

Ich muss eine Sitzung 30 Minuten lang am Leben halten und sie dann zerstören.

Tom
quelle
35
Bitte beachten Sie, dass mindestens zwei Einstellungen für die Einstellung der Sitzungszeit entscheidend sind, möglicherweise drei. Die beiden sicherlich entscheidenden sind session.gc_maxlifetime und session.cookie_lifetime (wobei 0 nicht mit einer langen Zahl identisch ist). Für eine vollständige, 100% ige Gewissheit, lange Zeiten zuzulassen, kann es auch erforderlich sein, den session.save_path festzulegen, da die vom Betriebssystem gesteuerte Bereinigungszeit im Verzeichnis / tmp variiert, in dem Sitzungsdateien standardmäßig gespeichert werden.
Kzqai
1
Ich verstehe nicht, warum Sie die Sitzung ablaufen lassen möchten. Wenn Sie befürchten, dass der Benutzer seinen Computer verlässt, ohne sich abzumelden, und ein nicht autorisierter Benutzer seinen Computer übernimmt, verhindert der Sitzungsablauf auf Ihrer Site nicht, dass der Entführer auf die Dateien des Opfers auf der Festplatte zugreift.
Gqqnbig
Es ist unklar, was Sie hier fragen. Meinen Sie damit, dass Sie ein Zeitlimit für harte Inaktivität implementieren möchten (derzeit können Sie mit PHP gerne eine Sitzung verwenden, die nicht länger als session.gc_maxlifetime berührt wurde), oder möchten Sie die Sitzung unabhängig davon auf 30 Minuten beschränken? Inaktivität? Ehrlich gesagt denke ich, dass die hier akzeptierte Antwort für beide Probleme eher ein schlechter Rat ist - in beiden Fällen sollte die Logik mit einem benutzerdefinierten Sitzungshandler implementiert werden.
Symcbean

Antworten:

1663

Sie sollten ein eigenes Sitzungszeitlimit implementieren. Beide von anderen genannten Optionen ( session.gc_maxlifetime und session.cookie_lifetime ) sind nicht zuverlässig. Ich werde die Gründe dafür erklären.

Zuerst:

session.gc_maxlifetime
session.gc_maxlifetime gibt die Anzahl der Sekunden an, nach denen Daten als "Müll" angesehen und bereinigt werden. Die Speicherbereinigung erfolgt während des Sitzungsstarts.

Der Garbage Collector wird jedoch nur mit einer Wahrscheinlichkeit von session.gc_probability geteilt durch session.gc_divisor gestartet . Bei Verwendung der Standardwerte für diese Optionen (1 bzw. 100) liegt die Chance nur bei 1%.

Sie können diese Werte einfach so anpassen, dass der Garbage Collector häufiger gestartet wird. Wenn der Garbage Collector gestartet wird, überprüft er die Gültigkeit für jede registrierte Sitzung. Und das ist kostenintensiv.

Wenn Sie die Standarddateien session.save_handler von PHP verwenden, werden die Sitzungsdaten in Dateien in einem in session.save_path angegebenen Pfad gespeichert . Mit diesem Sitzungshandler wird das Alter der Sitzungsdaten am letzten Änderungsdatum der Datei und nicht am letzten Zugriffsdatum berechnet:

Hinweis: Wenn Sie den standardmäßigen dateibasierten Sitzungshandler verwenden, muss Ihr Dateisystem die Zugriffszeiten (atime) verfolgen. Windows FAT funktioniert nicht, daher müssen Sie sich eine andere Möglichkeit einfallen lassen, um die Speicherbereinigung Ihrer Sitzung zu handhaben, wenn Sie mit einem FAT-Dateisystem oder einem anderen Dateisystem feststecken, für das keine Zeiterfassung verfügbar ist. Seit PHP 4.2.3 wird mtime (Änderungsdatum) anstelle von atime verwendet. Sie haben also keine Probleme mit Dateisystemen, in denen keine Zeiterfassung verfügbar ist.

Daher kann es zusätzlich vorkommen, dass eine Sitzungsdatendatei gelöscht wird, während die Sitzung selbst noch als gültig betrachtet wird, da die Sitzungsdaten kürzlich nicht aktualisiert wurden.

Und zweitens:

session.cookie_lifetime
session.cookie_lifetime gibt die Lebensdauer des Cookies in Sekunden an, das an den Browser gesendet wird. […]

Ja, das ist richtig. Dies wirkt sich nur auf die Lebensdauer der Cookies aus und die Sitzung selbst ist möglicherweise noch gültig. Es ist jedoch die Aufgabe des Servers, eine Sitzung ungültig zu machen, nicht der Client. Das hilft also nichts. In der Tat, mit session.cookie_lifetime zu Satz 0würde die Cookie - Sitzung eines echtes Session - Cookie , das nur gültig , bis der Browser geschlossen wird.

Fazit / beste Lösung:

Die beste Lösung besteht darin, ein eigenes Sitzungszeitlimit zu implementieren. Verwenden Sie einen einfachen Zeitstempel, der die Zeit der letzten Aktivität (dh Anforderung) angibt, und aktualisieren Sie ihn bei jeder Anforderung:

if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 1800)) {
    // last request was more than 30 minutes ago
    session_unset();     // unset $_SESSION variable for the run-time 
    session_destroy();   // destroy session data in storage
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp

Durch das Aktualisieren der Sitzungsdaten bei jeder Anforderung wird auch das Änderungsdatum der Sitzungsdatei geändert, sodass die Sitzung vom Garbage Collector nicht vorzeitig entfernt wird.

Sie können auch einen zusätzlichen Zeitstempel verwenden, um die Sitzungs-ID regelmäßig neu zu generieren, um Angriffe auf Sitzungen wie die Sitzungsfixierung zu vermeiden :

if (!isset($_SESSION['CREATED'])) {
    $_SESSION['CREATED'] = time();
} else if (time() - $_SESSION['CREATED'] > 1800) {
    // session started more than 30 minutes ago
    session_regenerate_id(true);    // change session ID for the current session and invalidate old session ID
    $_SESSION['CREATED'] = time();  // update creation time
}

Anmerkungen:

  • session.gc_maxlifetime sollte mindestens der Lebensdauer dieses benutzerdefinierten Ablaufbehandlungsprogramms entsprechen (in diesem Beispiel 1800);
  • Wenn Sie die Sitzung nach 30 Minuten Aktivität anstatt nach 30 Minuten seit dem Start ablaufen lassen möchten , müssen Sie sie auch setcookiemit einem Ablaufdatum von verwenden time()+60*30, um das Sitzungscookie aktiv zu halten.
Gumbo
quelle
3
Wie können Sie dies ändern, wenn Sie "Inaktive Zeit" überprüfen möchten? Mit anderen Worten, der Benutzer meldet sich an. Solange er die Site weiterhin verwendet, werden sie nicht abgemeldet. Wenn sie jedoch 30 Minuten lang inaktiv sind, werden sie abgemeldet.
Metropolis
14
@Metropolis: Verwenden Sie etwas Ähnliches $_SESSION['LAST_ACTIVITY']wie den Ort, an $_SESSION['CREATED']dem Sie die Zeit der letzten Aktivität des Benutzers speichern, aber aktualisieren Sie diesen Wert bei jeder Anforderung. Wenn der Unterschied zwischen dieser Zeit und der aktuellen Zeit größer als 1800 Sekunden ist, wurde die Sitzung nicht länger als 30 Minuten verwendet.
Gumbo
3
@ Metropolis: session_unsetmacht das gleiche wie $_SESSION = array().
Gumbo
14
@Gumbo - Ich bin ein bisschen verwirrt, solltest du deinen Code nicht in Kombination mit verwenden ini_set('session.gc-maxlifetime', 1800)? Andernfalls könnten Ihre Sitzungsinformationen zerstört werden, während Ihre Sitzung noch gültig sein soll, zumindest wenn die INI-Einstellung die Standardeinstellung von 24 Minuten ist. Oder fehlt mir etwas?
Jeroen
10
@ Jeron: Ja, das solltest du. Beachten Sie jedoch, dass session.gc_maxlifetime vom letzten Änderungsdatum der Datei abhängt, wenn der Session Save Handler filesverwendet wird. Daher sollte session.gc_maxlifetime mindestens der Lebensdauer dieses benutzerdefinierten Ablaufhandlers entsprechen.
Gumbo
135

Einfache Methode zum Ablauf der PHP-Sitzung in 30 Minuten.

Hinweis: Wenn Sie die Zeit ändern möchten, ändern Sie einfach die 30 mit der gewünschten Zeit und ändern Sie nicht * 60: Dies gibt die Minuten an.


In Minuten: (30 * 60)
In Tagen: (n * 24 * 60 * 60) n = Anzahl der Tage


Login.php

<?php
    session_start();
?>

<html>
    <form name="form1" method="post">
        <table>
            <tr>
                <td>Username</td>
                <td><input type="text" name="text"></td>
            </tr>
            <tr>
                <td>Password</td>
                <td><input type="password" name="pwd"></td>
            </tr>
            <tr>
                <td><input type="submit" value="SignIn" name="submit"></td>
            </tr>
        </table>
    </form>
</html>

<?php
    if (isset($_POST['submit'])) {
        $v1 = "FirstUser";
        $v2 = "MyPassword";
        $v3 = $_POST['text'];
        $v4 = $_POST['pwd'];
        if ($v1 == $v3 && $v2 == $v4) {
            $_SESSION['luser'] = $v1;
            $_SESSION['start'] = time(); // Taking now logged in time.
            // Ending a session in 30 minutes from the starting time.
            $_SESSION['expire'] = $_SESSION['start'] + (30 * 60);
            header('Location: http://localhost/somefolder/homepage.php');
        } else {
            echo "Please enter the username or password again!";
        }
    }
?>

HomePage.php

<?php
    session_start();

    if (!isset($_SESSION['luser'])) {
        echo "Please Login again";
        echo "<a href='http://localhost/somefolder/login.php'>Click Here to Login</a>";
    }
    else {
        $now = time(); // Checking the time now when home page starts.

        if ($now > $_SESSION['expire']) {
            session_destroy();
            echo "Your session has expired! <a href='http://localhost/somefolder/login.php'>Login here</a>";
        }
        else { //Starting this else one [else1]
?>
            <!-- From here all HTML coding can be done -->
            <html>
                Welcome
                <?php
                    echo $_SESSION['luser'];
                    echo "<a href='http://localhost/somefolder/logout.php'>Log out</a>";
                ?>
            </html>
<?php
        }
    }
?>

LogOut.php

<?php
    session_start();
    session_destroy();
    header('Location: http://localhost/somefolder/login.php');
?>
Rafee
quelle
42
Die Kombination von Logik und Präsentation ist heutzutage, wenn MVC die Norm ist, nicht ratsam.
Bcosca
Vielleicht fehlt mir etwas Grundlegendes an Sitzungen, aber was nützt das, wenn Sitzungen alle 30 Minuten vom Betriebssystem zerstört werden?
25
@stillstanding Sprich für dich [lächle] Ich betrachte MVC als Greuel.
2
Ist MVC eine gute Idee, auch wenn das Projekt klein ist, mit einem einzigen Programmierer? Ich habe das Gefühl, ich sollte meine eigenen Projekte im MVC-Modell erstellen (oder das Problem lösen, um es dann zu MVC zu machen), aber aufgrund mangelnder Erfahrung mit MVC wird es nur zu einer mentalen Blockade. "Wie mache ich diese MVC?" und eine Ablenkung vom ursprünglichen Ziel / Problem, das eine Lösung erfordert.
MrVimes
@ noch eine andere Erwähnung ist, dass auf Login.phpHeadern NACH dem Inhalt gesendet wird, was schlecht ist.
Machineaddict
43

Soll der Benutzer nach einer festgelegten Zeit abgemeldet werden? Wenn Sie die Erstellungszeit der Sitzung (oder eine Ablaufzeit) festlegen, wenn sie registriert wird, und dann überprüfen, ob bei jedem Laden der Seite dies möglich ist.

Z.B:

$_SESSION['example'] = array('foo' => 'bar', 'registered' => time());

// later

if ((time() - $_SESSION['example']['registered']) > (60 * 30)) {
    unset($_SESSION['example']);
}

Edit: Ich habe das Gefühl, du meinst aber etwas anderes.

Sie können Sitzungen nach einer bestimmten Lebensdauer mithilfe der session.gc_maxlifetimeINI-Einstellung verschrotten:

Bearbeiten: ini_set ('session.gc_maxlifetime', 60 * 30);

Ross
quelle
1
session.gc-maxlifetime ist wahrscheinlich der beste Weg.
Powerlord
2
Es gibt einige Probleme mit der Lebensdauer von Sitzungscookies, insbesondere, dass der Client sie durchsetzen muss. Die Cookie-Lebensdauer ermöglicht es dem Client, unbrauchbare / abgelaufene Cookies zu bereinigen. Sie darf nicht mit sicherheitsrelevanten Elementen verwechselt werden.
Jacco
Ist es gc_maxlifetimeoder gc-maxlifetime. Unterstützt es sowohl Unterstriche als auch Bindestriche?
Mike Causer
24

Dieser Beitrag zeigt verschiedene Möglichkeiten zur Steuerung des Sitzungszeitlimits: http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions

IMHO ist die zweite Option eine schöne Lösung:

<?php
/***
 * Starts a session with a specific timeout and a specific GC probability.
 * @param int $timeout The number of seconds until it should time out.
 * @param int $probability The probablity, in int percentage, that the garbage 
 *        collection routine will be triggered right now.
 * @param strint $cookie_domain The domain path for the cookie.
 */
function session_start_timeout($timeout=5, $probability=100, $cookie_domain='/') {
    // Set the max lifetime
    ini_set("session.gc_maxlifetime", $timeout);

    // Set the session cookie to timout
    ini_set("session.cookie_lifetime", $timeout);

    // Change the save path. Sessions stored in teh same path
    // all share the same lifetime; the lowest lifetime will be
    // used for all. Therefore, for this to work, the session
    // must be stored in a directory where only sessions sharing
    // it's lifetime are. Best to just dynamically create on.
    $seperator = strstr(strtoupper(substr(PHP_OS, 0, 3)), "WIN") ? "\\" : "/";
    $path = ini_get("session.save_path") . $seperator . "session_" . $timeout . "sec";
    if(!file_exists($path)) {
        if(!mkdir($path, 600)) {
            trigger_error("Failed to create session save path directory '$path'. Check permissions.", E_USER_ERROR);
        }
    }
    ini_set("session.save_path", $path);

    // Set the chance to trigger the garbage collection.
    ini_set("session.gc_probability", $probability);
    ini_set("session.gc_divisor", 100); // Should always be 100

    // Start the session!
    session_start();

    // Renew the time left until this session times out.
    // If you skip this, the session will time out based
    // on the time when it was created, rather than when
    // it was last used.
    if(isset($_COOKIE[session_name()])) {
        setcookie(session_name(), $_COOKIE[session_name()], time() + $timeout, $cookie_domain);
    }
}
Pablo Pazos
quelle
19

Nun, ich verstehe, dass die obigen Antworten korrekt sind, aber sie befinden sich auf Anwendungsebene. Warum verwenden wir nicht einfach die .htaccessDatei, um die Ablaufzeit festzulegen ?

<IfModule mod_php5.c>
    #Session timeout
    php_value session.cookie_lifetime 1800
    php_value session.gc_maxlifetime 1800
</IfModule>
Touqeer Shafi
quelle
1
Die Antwort von @ Lode gibt eine perfekte Erklärung dafür, warum diese Antwort unzuverlässig ist und nicht verwendet werden sollte.
Emix
15
if (isSet($_SESSION['started'])){
    if((mktime() - $_SESSION['started'] - 60*30) > 0){
        //Logout, destroy session, etc.
    }
}
else {
    $_SESSION['started'] = mktime();
}
middus
quelle
11

Mit einer Funktion wie der folgenden ist es eigentlich einfach. Es verwendet den Namen der Datenbanktabelle 'Sitzungen' mit den Feldern 'ID' und 'Zeit'.

Jedes Mal, wenn der Benutzer Ihre Site oder Ihren Dienst erneut besucht, sollten Sie diese Funktion aufrufen, um zu überprüfen, ob der Rückgabewert TRUE ist. Wenn es FALSE ist, ist der Benutzer abgelaufen und die Sitzung wird zerstört (Hinweis: Diese Funktion verwendet eine Datenbankklasse, um die Datenbank zu verbinden und abzufragen. Natürlich können Sie dies auch in Ihrer Funktion oder ähnlichem tun):

function session_timeout_ok() {
    global $db;
    $timeout = SESSION_TIMEOUT; //const, e.g. 6 * 60 for 6 minutes
    $ok = false;
    $session_id = session_id();
    $sql = "SELECT time FROM sessions WHERE session_id = '".$session_id."'";
    $rows = $db->query($sql);
    if ($rows === false) {
        //Timestamp could not be read
        $ok = FALSE;
    }
    else {
        //Timestamp was read succesfully
        if (count($rows) > 0) {
            $zeile = $rows[0];
            $time_past = $zeile['time'];
            if ( $timeout + $time_past < time() ) {
                //Time has expired
                session_destroy();
                $sql = "DELETE FROM sessions WHERE session_id = '" . $session_id . "'";
                $affected = $db -> query($sql);
                $ok = FALSE;
            }
            else {
                //Time is okay
                $ok = TRUE;
                $sql = "UPDATE sessions SET time='" . time() . "' WHERE session_id = '" . $session_id . "'";
                $erg = $db -> query($sql);
                if ($erg == false) {
                    //DB error
                }
            }
        }
        else {
            //Session is new, write it to database table sessions
            $sql = "INSERT INTO sessions(session_id,time) VALUES ('".$session_id."','".time()."')";
            $res = $db->query($sql);
            if ($res === FALSE) {
                //Database error
                $ok = false;
            }
            $ok = true;
        }
        return $ok;
    }
    return $ok;
}
Torsten Barthel
quelle
9

Speichern Sie einen Zeitstempel in der Sitzung


<?php    
$user = $_POST['user_name'];
$pass = $_POST['user_pass'];

require ('db_connection.php');

// Hey, always escape input if necessary!
$result = mysql_query(sprintf("SELECT * FROM accounts WHERE user_Name='%s' AND user_Pass='%s'", mysql_real_escape_string($user), mysql_real_escape_string($pass));

if( mysql_num_rows( $result ) > 0)
{
    $array = mysql_fetch_assoc($result);    

    session_start();
    $_SESSION['user_id'] = $user;
    $_SESSION['login_time'] = time();
    header("Location:loggedin.php");            
}
else
{
    header("Location:login.php");
}
?>

Überprüfen Sie nun, ob der Zeitstempel innerhalb des zulässigen Zeitfensters liegt (1800 Sekunden sind 30 Minuten).

<?php
session_start();
if( !isset( $_SESSION['user_id'] ) || time() - $_SESSION['login_time'] > 1800)
{
    header("Location:login.php");
}
else
{
    // uncomment the next line to refresh the session, so it will expire after thirteen minutes of inactivity, and not thirteen minutes after login
    //$_SESSION['login_time'] = time();
    echo ( "this session is ". $_SESSION['user_id'] );
    //show rest of the page and all other content
}
?>
Alpesh Rathod
quelle
8

Bitte verwenden Sie den folgenden Codeblock in Ihrer Include-Datei, der auf allen Seiten geladen wird.

$expiry = 1800 ;//session expiry required after 30 mins
    if (isset($_SESSION['LAST']) && (time() - $_SESSION['LAST'] > $expiry)) {
        session_unset();
        session_destroy();
    }
    $_SESSION['LAST'] = time();
lnepal
quelle
1

Verwenden Sie diese Klasse für 30 Minuten

class Session{
    public static function init(){
        ini_set('session.gc_maxlifetime', 1800) ;
        session_start();
    }
    public static function set($key, $val){
        $_SESSION[$key] =$val;
    }
    public static function get($key){
        if(isset($_SESSION[$key])){
            return $_SESSION[$key];
        } else{
            return false;
        }
    }
    public static function checkSession(){
        self::init();
        if(self::get("adminlogin")==false){
            self::destroy();
            header("Location:login.php");
        }
    }
    public static function checkLogin(){
        self::init();
        if(self::get("adminlogin")==true){
            header("Location:index.php");
        }
    }
    public static function destroy(){
        session_destroy();
        header("Location:login.php");
    }
}
Amranur Rahman
quelle
0

Zeitstempel verwenden ...

<?php
if (!isset($_SESSION)) {
    $session = session_start();
} 
if ($session && !isset($_SESSION['login_time'])) {
    if ($session == 1) {
        $_SESSION['login_time']=time();
        echo "Login :".$_SESSION['login_time'];
        echo "<br>";
        $_SESSION['idle_time']=$_SESSION['login_time']+20;
        echo "Session Idle :".$_SESSION['idle_time'];
        echo "<br>";
    } else{
        $_SESSION['login_time']="";
    }
} else {
    if (time()>$_SESSION['idle_time']){
        echo "Session Idle :".$_SESSION['idle_time'];
        echo "<br>";
        echo "Current :".time();
        echo "<br>";
        echo "Session Time Out";
        session_destroy();
        session_unset();
    } else {
        echo "Logged In<br>";
    }
}
?>

Ich habe 20 Sekunden verwendet, um die Sitzung mit dem Zeitstempel abzulaufen .

Wenn Sie 30 Minuten benötigen, fügen Sie 1800 hinzu (30 Minuten in Sekunden) ...

Sarvan Kumar
quelle
0

Alternativ können Sie auch eine Datenbank verwenden. Ich benutze dazu eine DB-Funktion, die ich chk_lgn aufrufe.

Überprüfen Sie die Anmeldeprüfungen, um festzustellen, ob sie angemeldet sind oder nicht. Dabei wird der Datums- und Zeitstempel der Prüfung als zuletzt aktiv in der Datenbankzeile / -spalte des Benutzers festgelegt.

Dort überprüfe ich auch die Zeit. Dies funktioniert für mich im Moment, da ich diese Funktion für jede Seite verwende.

PS Niemand, den ich gesehen hatte, hatte eine reine DB-Lösung vorgeschlagen.

JSG
quelle
-1

Speichern Sie einfach die aktuelle Zeit und zerstören Sie die aktuelle Sitzung, wenn sie beim Vergleich 30 Minuten überschreitet.

Narendra Sharma
quelle
Das würden Sie nur dann bewerten, wenn Sie die Sitzung verwenden, oder?
Eric Kramer