Bagaimana saya berakhir sesi PHP setelah 30 menit?

1047

Saya perlu menjaga sesi tetap hidup selama 30 menit dan kemudian menghancurkannya.

Tom
sumber
35
Harap dicatat bahwa setidaknya dua pengaturan sangat penting untuk mengatur waktu sesi, dan mungkin tiga. Dua yang pasti penting adalah session.gc_maxlifetime dan session.cookie_lifetime (di mana 0 tidak sama dengan beberapa nomor lama). Untuk menyelesaikan, kepastian 100% untuk waktu yang lama, mungkin juga diperlukan untuk mengatur session.save_path, karena beragam waktu pembersihan yang dikontrol OS pada direktori / tmp di mana file sesi disimpan secara default.
Kzqai
1
Saya tidak mengerti mengapa Anda ingin berakhir sesi. Jika Anda khawatir pengguna meninggalkan komputernya tanpa keluar, dan pengguna yang tidak sah mengambil alih komputernya, sesi yang berakhir pada situs Anda tidak akan mencegah pembajak mengakses file korban pada disk.
Gqqnbig
Tidak jelas apa yang Anda tanyakan di sini. Maksud Anda ingin menerapkan batas waktu tidak aktif yang sulit (saat ini PHP dengan senang hati akan membiarkan Anda menggunakan sesi yang belum tersentuh selama lebih dari session.gc_maxlifetime) atau apakah Anda bermaksud membatasi sesi hingga 30 menit terlepas dari tidak aktif? Terus terang saya pikir jawaban yang diterima di sini adalah saran yang agak buruk untuk kedua masalah - dalam kedua kasus logika harus diimplementasikan dengan pengendali sesi kustom.
symcbean

Jawaban:

1663

Anda harus menerapkan batas waktu sesi Anda sendiri. Kedua opsi yang disebutkan oleh orang lain ( session.gc_maxlifetime dan session.cookie_lifetime ) tidak dapat diandalkan. Saya akan menjelaskan alasannya.

Pertama:

session.gc_maxlifetime
session.gc_maxlifetime menentukan jumlah detik setelah data yang akan dilihat sebagai 'sampah' dan dibersihkan. Pengumpulan sampah terjadi selama sesi dimulai.

Tetapi pengumpul sampah hanya dimulai dengan probabilitas session.gc_probability dibagi dengan session.gc_divisor . Dan menggunakan nilai default untuk opsi-opsi tersebut (masing-masing 1 dan 100), peluangnya hanya 1%.

Nah, Anda bisa menyesuaikan nilai-nilai ini sehingga pengumpul sampah mulai lebih sering. Tetapi ketika pemulung mulai, itu akan memeriksa validitas untuk setiap sesi terdaftar. Dan itu mahal.

Selanjutnya, saat menggunakan file session.save_handler default PHP , data sesi disimpan dalam file di jalur yang ditentukan dalam session.save_path . Dengan pengendali sesi itu, usia data sesi dihitung pada tanggal modifikasi terakhir file dan bukan tanggal akses terakhir:

catatan: Jika Anda menggunakan pengendali sesi berbasis file default, sistem file Anda harus melacak waktu akses (atime). Windows FAT tidak jadi Anda harus datang dengan cara lain untuk menangani pengumpulan sampah sesi Anda jika Anda terjebak dengan sistem file FAT atau sistem file lain di mana pelacakan atime tidak tersedia. Sejak PHP 4.2.3 telah menggunakan mtime (tanggal modifikasi) bukan atime. Jadi, Anda tidak akan memiliki masalah dengan sistem file di mana pelacakan atime tidak tersedia.

Jadi mungkin juga terjadi bahwa file data sesi dihapus sementara sesi itu sendiri masih dianggap valid karena data sesi tidak diperbarui baru-baru ini.

Dan kedua:

session.cookie_lifetime
session.cookie_lifetime menentukan umur cookie dalam detik yang dikirim ke browser. [...]

Ya itu betul. Ini hanya memengaruhi masa pakai cookie dan sesi itu sendiri mungkin masih valid. Tapi itu tugas server untuk membatalkan sesi, bukan klien. Jadi ini tidak membantu apa pun. Bahkan, mengatur session.cookie_lifetime0 akan menjadikan cookie sesi tersebut sebagai cookie sesi nyata yang hanya valid hingga browser ditutup.

Kesimpulan / solusi terbaik:

Solusi terbaik adalah menerapkan batas waktu sesi Anda sendiri. Gunakan cap waktu sederhana yang menunjukkan waktu aktivitas terakhir (mis. Permintaan) dan perbarui dengan setiap permintaan:

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

Memperbarui data sesi dengan setiap permintaan juga mengubah tanggal modifikasi file sesi sehingga sesi tersebut tidak dihapus oleh pengumpul sampah secara prematur.

Anda juga dapat menggunakan cap waktu tambahan untuk membuat ulang ID sesi secara berkala untuk menghindari serangan pada sesi seperti fiksasi sesi :

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
}

Catatan:

  • session.gc_maxlifetime harus setidaknya sama dengan masa berlaku penangan kedaluwarsa khusus ini (1800 dalam contoh ini);
  • jika Anda ingin kedaluwarsa sesi setelah 30 menit aktivitas alih-alih setelah 30 menit sejak mulai , Anda juga harus menggunakan setcookiedengan kadaluwarsa time()+60*30untuk menjaga cookie sesi aktif.
Gumbo
sumber
3
Bagaimana Anda dapat mengubah ini jika Anda ingin memeriksa "waktu tidak aktif"? Dengan kata lain, pengguna log in, dan selama mereka terus menggunakan situs, itu tidak akan keluar. Namun jika mereka tidak aktif selama 30 menit itu akan keluar?
Metropolis
14
@Metropolis: Gunakan sesuatu yang $_SESSION['LAST_ACTIVITY']mirip dengan $_SESSION['CREATED']tempat Anda menyimpan waktu aktivitas terakhir pengguna tetapi perbarui nilai itu dengan setiap permintaan. Sekarang jika perbedaan waktu itu dengan waktu saat ini lebih besar dari 1800 detik, sesi belum digunakan selama lebih dari 30 menit.
Gumbo
3
@Metropolis: session_unsetmelakukan hal yang sama dengan $_SESSION = array().
Gumbo
14
@ Gumbo - Saya agak bingung, bukankah sebaiknya Anda menggunakan kode Anda bersama ini_set('session.gc-maxlifetime', 1800)? Kalau tidak, informasi sesi Anda dapat dihancurkan saat sesi Anda seharusnya masih valid, setidaknya jika pengaturan ini adalah standar 24 menit. Atau apakah saya melewatkan sesuatu?
Jeroen
10
@ Jonathan: Ya, Anda harus. Tetapi perhatikan bahwa session.gc_maxlifetime tergantung pada tanggal modifikasi file terakhir jika sesi save handler filesdigunakan. Jadi session.gc_maxlifetime harus setidaknya sama dengan waktu hidup penangan kedaluwarsa kustom ini.
Gumbo
135

Cara sederhana sesi PHP kedaluwarsa dalam 30 menit.

Catatan: jika Anda ingin mengubah waktu, ubah saja 30 dengan waktu yang Anda inginkan dan jangan ubah * 60: ini akan memberi waktu.


Dalam menit: (30 * 60)
Dalam hari: (n * 24 * 60 * 60) n = tidak ada hari


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
sumber
42
Menggabungkan logika dan presentasi adalah keliru di zaman sekarang ketika MVC adalah norma.
bcosca
Mungkin saya kehilangan sesuatu yang mendasar tentang sesi, tetapi apa gunanya ini jika sesi dihancurkan setiap 30 menit oleh OS?
25
@stillstanding Berbicara untuk diri sendiri [tersenyum] Saya melihat MVC sebagai kekejian.
2
Apakah MVC ide yang baik bahkan ketika proyeknya kecil, dengan satu programmer? Saya merasa seperti saya harus membuat proyek saya sendiri dalam model MVC (atau menyelesaikan masalah MAKA membuatnya MVC) tetapi dengan kurangnya pengalaman dengan MVC itu hanya menjadi hambatan mental "Bagaimana cara membuat MVC ini?" dan gangguan dari tujuan awal / masalah yang membutuhkan solusi.
MrVimes
@stillstanding menyebutkan lain adalah bahwa pada Login.phpheader dikirim SETELAH konten, yang buruk.
machineaddict
43

Apakah ini untuk mengeluarkan pengguna setelah waktu yang ditentukan? Mengatur waktu pembuatan sesi (atau waktu kedaluwarsa) saat terdaftar, dan kemudian memeriksa bahwa pada setiap pemuatan halaman dapat mengatasinya.

Misalnya:

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

// later

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

Sunting: Saya punya perasaan Anda berarti sesuatu yang lain.

Anda dapat membatalkan sesi setelah jangka waktu tertentu dengan menggunakan session.gc_maxlifetimepengaturan ini:

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

Ross
sumber
1
session.gc-maxlifetime mungkin adalah cara terbaik untuk pergi.
Powerlord
2
Ada beberapa masalah dengan cookie seumur hidup sesi, terutama, itu bergantung pada klien untuk menegakkannya. Cookie seumur hidup ada untuk memungkinkan klien untuk membersihkan cookie yang tidak berguna / kedaluwarsa, tidak perlu bingung dengan keamanan apa pun yang terkait.
Jacco
Apakah itu gc_maxlifetimeatau gc-maxlifetime. Apakah itu mendukung garis bawah dan tanda hubung?
Mike Causer
24

Posting ini menunjukkan beberapa cara untuk mengendalikan batas waktu sesi: http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions

IMHO opsi kedua adalah solusi yang bagus:

<?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
sumber
19

Yah saya mengerti jawaban di atas sudah benar tetapi mereka berada di tingkat aplikasi, mengapa kita tidak menggunakan .htaccessfile untuk mengatur waktu kedaluwarsa?

<IfModule mod_php5.c>
    #Session timeout
    php_value session.cookie_lifetime 1800
    php_value session.gc_maxlifetime 1800
</IfModule>
Touqeer Shafi
sumber
1
@ Lode's answer memberikan penjelasan yang sempurna mengapa jawaban ini tidak dapat diandalkan tidak boleh digunakan.
emix
15
if (isSet($_SESSION['started'])){
    if((mktime() - $_SESSION['started'] - 60*30) > 0){
        //Logout, destroy session, etc.
    }
}
else {
    $_SESSION['started'] = mktime();
}
middus
sumber
15

Gunakan fungsi session_set_cookie_paramsuntuk membuat ini.

Apakah perlu memanggil fungsi ini sebelumnya session_start() panggilan.

Coba ini:

$lifetime = strtotime('+30 minutes', 0);

session_set_cookie_params($lifetime);

session_start();

Lihat lebih lanjut di: http://php.net/manual/function.session-set-cookie-params.php

Wallace Maxters
sumber
11

Ini sebenarnya mudah dengan fungsi seperti berikut. Ini menggunakan nama tabel database 'sesi' dengan bidang 'id' dan 'waktu'.

Setiap kali ketika pengguna mengunjungi situs atau layanan Anda lagi, Anda harus menjalankan fungsi ini untuk memeriksa apakah nilai pengembaliannya BENAR. Jika SALAH, pengguna telah kedaluwarsa dan sesi akan dimusnahkan (Catatan: Fungsi ini menggunakan kelas basis data untuk menyambungkan dan meminta basis data, tentu saja Anda juga bisa melakukannya di dalam fungsi Anda atau semacamnya):

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
sumber
9

Simpan stempel waktu di sesi


<?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");
}
?>

Sekarang, periksa apakah cap waktu berada dalam jendela waktu yang diizinkan (1800 detik adalah 30 menit)

<?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
sumber
8

Silakan gunakan blok kode berikut dalam file sertakan Anda yang dimuat di setiap halaman.

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

Gunakan kelas ini selama 30 menit

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
sumber
0

Menggunakan stempel waktu ...

<?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>";
    }
}
?>

Saya telah menggunakan 20 detik untuk berakhir sesi menggunakan cap waktu .

Jika Anda membutuhkan 30 menit, tambahkan 1800 (30 mnt dalam detik) ...

Sarvan Kumar
sumber
0

Anda dapat langsung menggunakan DB untuk melakukannya sebagai alternatif. Saya menggunakan fungsi DB untuk melakukannya yang saya sebut chk_lgn.

Periksa cek masuk untuk melihat apakah mereka masuk atau tidak dan, dengan melakukan itu, ia menetapkan cap waktu tanggal cek sebagai yang terakhir aktif di baris / kolom db pengguna.

Saya juga melakukan pengecekan waktu di sana. Ini berfungsi untuk saya saat ini karena saya menggunakan fungsi ini untuk setiap halaman.

PS Tidak ada yang saya lihat menyarankan solusi DB murni.

JSG
sumber
0

Bagaimana PHP menangani sesi cukup membingungkan untuk dipahami pemula. Ini mungkin membantu mereka dengan memberikan gambaran umum tentang bagaimana sesi bekerja: bagaimana sesi bekerja (custom-session-handler)

pengguna123456789
sumber
-1

Simpan saja waktu saat ini dan Jika melebihi 30 menit dengan membandingkan maka hancurkan sesi saat ini.

Narendra Sharma
sumber
Satu-satunya waktu Anda mengevaluasi itu adalah ketika menggunakan sesi, kan?
Eric Kramer