Bagaimana cara mengubah batas waktu sesi dalam PHP?

154

Saya ingin memperpanjang batas waktu sesi di php

Saya tahu mungkin untuk melakukannya dengan memodifikasi file php.ini. Tetapi saya tidak memiliki akses ke sana.

Jadi mungkinkah melakukannya hanya dengan kode php?

Oli
sumber
1
Terkait, ini ada di php.ini, tapi saya pikir Anda bisa menggunakan ini_set seperti @matino berkata stackoverflow.com/questions/520237/…
J-Rou

Jawaban:

324

Batas waktu sesi adalah gagasan yang harus diterapkan dalam kode jika Anda menginginkan jaminan ketat; itulah satu-satunya cara Anda dapat benar-benar yakin bahwa tidak ada sesi yang akan bertahan setelah X menit tidak aktif.

Jika melonggarkan persyaratan ini sedikit dapat diterima dan Anda baik-baik saja dengan menempatkan batas bawah alih-alih batas waktu yang ketat, Anda dapat melakukannya dengan mudah dan tanpa menulis logika khusus.

Kenyamanan dalam lingkungan yang santai: bagaimana dan mengapa

Jika sesi Anda diimplementasikan dengan cookie (yang mungkin), dan jika klien tidak berbahaya, Anda dapat menetapkan batas atas pada durasi sesi dengan mengubah parameter tertentu. Jika Anda menggunakan standar sesi penanganan PHP dengan cookie, pengaturan session.gc_maxlifetimebersama dengan session_set_cookie_paramsharus bekerja untuk Anda seperti ini:

// server should keep session data for AT LEAST 1 hour
ini_set('session.gc_maxlifetime', 3600);

// each client should remember their session id for EXACTLY 1 hour
session_set_cookie_params(3600);

session_start(); // ready to go!

Ini berfungsi dengan mengonfigurasi server agar data sesi tetap ada selama setidaknya satu jam tidak aktif dan memberi tahu klien Anda bahwa mereka harus "lupa" id sesi mereka setelah rentang waktu yang sama. Kedua langkah ini diperlukan untuk mencapai hasil yang diharapkan.

  • Jika Anda tidak memberi tahu klien untuk melupakan id sesi mereka setelah satu jam (atau jika klien berbahaya dan memilih untuk mengabaikan instruksi Anda) mereka akan tetap menggunakan id sesi yang sama dan durasi efektifnya akan menjadi non-deterministik. Itu karena sesi yang masa hidupnya telah berakhir pada sisi server tidak segera dikumpulkan sampah tetapi hanya setiap kali sesi GC dimulai .

    GC adalah proses yang berpotensi mahal, jadi biasanya probabilitasnya agak kecil atau bahkan nol (situs web yang mendapatkan jumlah besar hit mungkin akan melupakan GC probabilistik sepenuhnya dan menjadwalkannya terjadi di latar belakang setiap X menit). Dalam kedua kasus (dengan asumsi klien yang tidak bekerja sama) batas bawah untuk masa pakai sesi yang efektif adalah session.gc_maxlifetime, tetapi batas atas tidak dapat diprediksi.

  • Jika Anda tidak menetapkan session.gc_maxlifetimerentang waktu yang sama maka server mungkin membuang data sesi siaga lebih awal dari itu; dalam hal ini, klien yang masih mengingat id sesi mereka akan menyajikannya tetapi server tidak akan menemukan data yang terkait dengan sesi itu, berperilaku efektif seolah-olah sesi baru saja dimulai.

Kepastian dalam lingkungan kritis

Anda dapat membuat segala sesuatu sepenuhnya dapat dikontrol dengan menggunakan logika khusus untuk juga menempatkan batas atas pada tidak aktif sesi; bersama dengan batas bawah dari atas ini menghasilkan pengaturan yang ketat.

Lakukan ini dengan menyimpan batas atas bersama dengan sisa data sesi:

session_start(); // ready to go!

$now = time();
if (isset($_SESSION['discard_after']) && $now > $_SESSION['discard_after']) {
    // this session has worn out its welcome; kill it and start a brand new one
    session_unset();
    session_destroy();
    session_start();
}

// either new or old, it should live at most for another hour
$_SESSION['discard_after'] = $now + 3600;

Sesi id kegigihan

Sejauh ini kami sama sekali tidak peduli dengan nilai yang tepat dari setiap sesi id, hanya dengan persyaratan bahwa data harus ada selama kami membutuhkannya. Sadarilah bahwa dalam kasus (tidak mungkin) bahwa id sesi penting bagi Anda, harus ada perhatian untuk memperbaharui mereka session_regenerate_idketika diperlukan.

Jon
sumber
Pertanyaan: jika memanggil ini, katakan saja setiap menit, apakah akan meningkatkan batasnya? contoh pada jam 10:00 saya menyebutnya batasnya adalah 11:00, setelah 1 menit, 10:01, apakah batasnya 11:01?
oneofakind
@ Oneofakind: Jika Anda memanggil apa sebenarnya?
Jon
1
Yang ini: ini_set ('session.gc_maxlifetime', 3600); session_set_cookie_params (3600);
oneofakind
@ oneofakind: Ya, tetapi hanya jika Anda memanggil session_start()juga (jika tidak ada efek sama sekali) dan hanya jika Anda selalu memanggil keduanya sebelumnya session_start(jika tidak gc_maxlifetimememiliki potensi untuk mempengaruhi semua sesi saat ini terbuka, sementara session_set_cookie_paramshanya dapat mempengaruhi sesi baru yang dimulai dengan permintaan saat ini).
Jon
@Jon jika saya memanggil session_start () lagi apakah ini akan mengatur ulang semua dalam $ _SESSION saya? jika Anda maksud dengan "memiliki potensi untuk mempengaruhi semua sesi" bagaimana bisa begitu? Terima kasih balasannya.
oneofakind
33

Jika Anda menggunakan penanganan sesi default PHP, satu-satunya cara untuk secara andal mengubah durasi sesi di semua platform adalah dengan mengubah php.ini . Itu karena di beberapa platform, pengumpulan sampah diimplementasikan melalui skrip yang berjalan setiap waktu tertentu ( skrip cron ) yang dibaca langsung dari php.ini , dan oleh karena itu segala upaya untuk mengubahnya pada waktu berjalan, misalnya melalui ini_set(), tidak dapat diandalkan dan kemungkinan besar tidak akan bekerja

Misalnya, dalam sistem Debian Linux, pengumpulan sampah internal PHP dinonaktifkan dengan pengaturan session.gc_probability=0secara default dalam konfigurasi, dan sebaliknya dilakukan melalui /etc/cron.d/php, yang berjalan di XX: 09 dan XX: 39 (yaitu, setiap setengah jam). Pekerjaan cron ini mencari sesi yang lebih lama dari session.gc_maxlifetime yang ditentukan dalam konfigurasi, dan jika ada yang ditemukan, mereka dihapus. Akibatnya, dalam sistem ini_set('session.gc_maxlifetime', ...)ini diabaikan. Itu juga menjelaskan mengapa dalam pertanyaan ini: sesi PHP terlalu cepat , OP memiliki masalah dalam satu host tetapi masalah berhenti ketika beralih ke host yang berbeda.

Jadi, mengingat Anda tidak memiliki akses ke php.ini , jika Anda ingin melakukannya dengan mudah, menggunakan penanganan sesi default bukanlah suatu pilihan. Tampaknya, memperpanjang umur cookie sudah cukup untuk host Anda, tetapi jika Anda menginginkan solusi yang dapat diandalkan bahkan jika Anda mengganti host, Anda harus menggunakan alternatif lain.

Metode alternatif yang tersedia meliputi:

  1. Tetapkan penangan sesi (simpan) yang berbeda di PHP untuk menyimpan sesi Anda di direktori yang berbeda atau dalam database, sebagaimana ditentukan dalam PHP: Penangan Sesi Kustom (manual PHP) , sehingga tugas cron tidak mencapainya, dan hanya PHP yang pengumpulan sampah internal berlangsung. Opsi ini mungkin dapat digunakan ini_set()untuk mengatur session.gc_maxlifetime tetapi saya lebih suka mengabaikan parameter maxlifetime di gc()callback saya dan menentukan masa pakai maksimum saya sendiri.

  2. Lupakan tentang penanganan sesi internal PHP dan laksanakan manajemen sesi Anda sendiri. Metode ini memiliki dua kelemahan utama: Anda akan memerlukan variabel sesi global Anda sendiri, sehingga Anda kehilangan keunggulan $_SESSIONsuperglobal, dan itu membutuhkan lebih banyak kode sehingga ada lebih banyak peluang untuk bug dan kelemahan keamanan. Yang paling penting, pengidentifikasi sesi harus dihasilkan dari nomor acak acak atau pseudorandom untuk menghindari prediktabilitas ID sesi (yang mengarah ke kemungkinan pembajakan sesi), dan itu tidak mudah dilakukan dengan PHP dengan mudah. Keuntungan utama adalah ia akan bekerja secara konsisten di semua platform dan Anda memiliki kontrol penuh atas kode. Itu pendekatan yang diambil misalnya oleh perangkat lunak forum phpBB (setidaknya versi 1; Saya tidak yakin tentang versi yang lebih baru).

Ada contoh (1) dalam dokumentasi untuksession_set_save_handler() . Contohnya panjang tapi saya akan mereproduksi di sini, dengan modifikasi yang relevan diperlukan untuk memperpanjang durasi sesi. Perhatikan dimasukkannya session_set_cookie_params()untuk meningkatkan umur cookie juga.

<?php
class FileSessionHandler
{

    private $savePath;
    private $lifetime;

    function open($savePath, $sessionName)
    {
        $this->savePath = 'my_savepath'; // Ignore savepath and use our own to keep it safe from automatic GC
        $this->lifetime = 3600; // 1 hour minimum session duration
        if (!is_dir($this->savePath)) {
            mkdir($this->savePath, 0777);
        }

        return true;
    }

    function close()
    {
        return true;
    }

    function read($id)
    {
        return (string)@file_get_contents("$this->savePath/sess_$id");
    }

    function write($id, $data)
    {
        return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
    }

    function destroy($id)
    {
        $file = "$this->savePath/sess_$id";
        if (file_exists($file)) {
            unlink($file);
        }

        return true;
    }

    function gc($maxlifetime)
    {
        foreach (glob("$this->savePath/sess_*") as $file) {
            if (filemtime($file) + $this->lifetime < time() && file_exists($file)) { // Use our own lifetime
                unlink($file);
            }
        }

        return true;
    }
}

$handler = new FileSessionHandler();
session_set_save_handler(
    array($handler, 'open'),
    array($handler, 'close'),
    array($handler, 'read'),
    array($handler, 'write'),
    array($handler, 'destroy'),
    array($handler, 'gc')
    );

// the following prevents unexpected effects when using objects as save handlers
register_shutdown_function('session_write_close');

session_set_cookie_params(3600); // Set session cookie duration to 1 hour
session_start();
// proceed to set and retrieve values by key from $_SESSION

Pendekatan (2) lebih rumit; pada dasarnya, Anda harus mengimplementasikan kembali semua fungsi sesi Anda sendiri. Saya tidak akan membahas detailnya di sini.

Pedro Gimeno
sumber
Adakah yang bisa mengkonfirmasi itu?
Oli
@ Oli: Itu terlihat benar setelah membaca sepintas. Anda mungkin juga ingin melihat stackoverflow.com/questions/520237/… , tetapi jika Anda tidak memiliki akses ke php.iniopsi praktis Anda sangat dibatasi.
Jon
Juga, pada Ubuntu 14 sepertinya /usr/lib/php5/maxlifetimetidak akan menghitung nilai di bawah 24 menit. Jadi Anda tidak dapat mengatur batas waktu sesi Anda lebih rendah dari itu.
Henry
"Benar-benar lupa tentang penanganan sesi internal PHP dan terapkan manajemen sesi Anda sendiri." Ya Tuhan, itu nasihat yang berbahaya. Mimpi buruk keamanan pasti akan terjadi.
Kzqai
@ Kzqai Saya juga mencatat bahwa "perlu lebih banyak kode sehingga ada lebih banyak peluang untuk bug dan kelemahan keamanan". Ini bukan saran, saya sedang menghitung alternatif, tetapi jika Anda memiliki saran untuk memperbaikinya, silakan lakukan.
Pedro Gimeno
3

Menambahkan komentar untuk siapa pun yang menggunakan Plesk mengalami masalah dengan hal-hal di atas karena hal itu membuat saya gila, mengatur session.gc_maxlifetime dari skrip PHP Anda tidak akan berfungsi karena Plesk memiliki skrip pengumpulan sampah sendiri yang dijalankan dari cron.

Saya menggunakan solusi yang diposting pada tautan di bawah ini untuk memindahkan pekerjaan cron dari jam ke hari untuk menghindari masalah ini, maka jawaban teratas di atas seharusnya bekerja:

mv /etc/cron.hourly/plesk-php-cleanuper /etc/cron.daily/

https://websavers.ca/plesk-php-sessions-timing-earlier-expected

Neil Walden
sumber
3

Masukkan $_SESSION['login_time'] = time();ke halaman otentikasi sebelumnya. Dan potongan di bawah ini di setiap halaman lain di mana Anda ingin memeriksa batas waktu sesi.

if(time() - $_SESSION['login_time'] >= 1800){
    session_destroy(); // destroy session.
    header("Location: logout.php");
    die(); // See https://thedailywtf.com/articles/WellIntentioned-Destruction
    //redirect if the page is inactive for 30 minutes
}
else {        
   $_SESSION['login_time'] = time();
   // update 'login_time' to the last time a page containing this code was accessed.
}

Sunting: Ini hanya berfungsi jika Anda sudah menggunakan tweak di posting lain, atau menonaktifkan Pengumpulan Sampah, dan ingin memeriksa durasi sesi secara manual. Jangan lupa untuk menambahkan die()setelah pengalihan, karena beberapa skrip / robot mungkin mengabaikannya. Juga, langsung menghancurkan sesi dengan session_destroy()alih - alih mengandalkan pengalihan untuk itu mungkin menjadi pilihan yang lebih baik, sekali lagi, dalam kasus klien jahat atau robot.

mohamadRezaSamadi
sumber
2

Hanya pemberitahuan untuk server hosting berbagi atau ditambahkan di domain =

Agar pengaturan Anda berfungsi, Anda harus memiliki dir sesi penyimpanan yang berbeda untuk domain yang ditambahkan dengan menggunakan php_value session.save_path "folderA / sessionA".

Jadi buat folder ke server root Anda, jangan ke public_html dan jangan sampai publisitas diakses dari luar. Untuk cpanel / server saya berfungsi dengan baik izin folder 0700. Cobalah ...

  • kode php =

     #Session timeout, 2628000 sec = 1 month, 604800 = 1 week, 57600 = 16 hours, 86400 = 1 day
     ini_set('session.save_path', '/home/server/.folderA_sessionsA');
     ini_set('session.gc_maxlifetime', 57600); 
     ini_set('session.cookie_lifetime', 57600);
     ini_set('session.cache_expire', 57600);
     ini_set('session.name', 'MyDomainA');

sebelum session_start ();

atau

  • .htaccess =

     php_value session.save_path /home/server/.folderA_sessionsA
     php_value session.gc_maxlifetime 57600
     php_value session.cookie_lifetime 57600
     php_value session.cache_expire 57600
     php_value session.name MyDomainA

Setelah banyak meneliti dan menguji ini bekerja dengan baik untuk server cpanel / php7 bersama. Banyak terima kasih kepada: NoiS

ChriStef
sumber
1

Tidak. Jika Anda tidak memiliki akses ke php.ini, Anda tidak dapat menjamin bahwa perubahan akan berdampak apa pun.

Saya ragu Anda perlu memperpanjang waktu sesi Anda.
Ini memiliki batas waktu yang cukup masuk akal saat ini dan tidak ada alasan untuk memperpanjangnya.

Akal Sehat Anda
sumber
Hai Kol, saya telah mencari ke seluruh tempat ini untuk menemukan cara untuk menghubungi Anda. Saya melihat bahwa Anda memberi saya beberapa saran pada posting terakhir saya yang ditutup (Minggu.) Saya sibuk dengan proyek lain dan sekarang sudah tidak ada. Saya benar-benar ingin mencoba saran Anda. Ini ada untuk menemukan apa yang Anda tulis?
Anjing tua
Sejauh yang saya lihat, itu tidak hanya ditutup, tetapi juga dihapus. Orang-orang ini tidak punya kehormatan. Ya, masalah Anda memiliki solusi umum yang saya bicarakan. Saya akan menulis kepada Anda melalui email. Singkatnya, ini tentang menjalankan 2 kueri tambahan untuk mendapatkan nilai prev / next ini. SELECT id FROM gallery WHERE SortOrder > $currentsortorder LIMIT 1
Akal Sehat Anda
0

Anda dapat mengganti nilai dalam php.ini dari kode PHP Anda menggunakan ini_set().

Nathan Q
sumber
4
-1: session.gc_maxlifetimebukan pengaturan yang mengontrol masa pakai sesi. Hal ini dapat dipukul dengan pekerjaan seperti itu jika Anda mengatur session.gc_divisoruntuk 1, tapi itu hanya mengerikan.
Jon
1
@Jon Saya telah melihat begitu banyak jawaban pada SO menyarankan sebaliknya, mengapa begitu? stackoverflow.com/questions/514155/… stackoverflow.com/questions/9904105/…
giannis christofakis
2
@ yannishristofakis: gc_maxlifetimemenetapkan interval setelah data sesi memenuhi syarat untuk pengumpulan sampah - jika GC terjadi setelah waktu yang banyak berlalu, data sesi akan dihancurkan (dengan pengaturan default ini sama dengan berakhirnya sesi). Tetapi GC dipicu secara probabilistik pada setiap awal sesi, jadi tidak ada jaminan sesi akan benar-benar berakhir - Anda dapat merencanakan kurva prob vs waktu, tetapi tidak akan terlihat seperti dinding bata. Itu hanya puncak gunung es; lihat stackoverflow.com/questions/520237/…
Jon