PHP'de oturum zaman aşımı nasıl değiştirilir?


Yanıtlar:


324

Oturum zaman aşımı, katı garantiler istiyorsanız kodda uygulanması gereken bir kavramdır; olduğunu tek yolu hiçbir oturumun hiç hareketsizlik X dakika sonra hayatta kalacaktır kesinlikle emin olabilirsiniz.

Bu gereksinimi rahatlatmak biraz kabul edilebilirse ve süreye sıkı bir sınır koymak yerine bir alt sınır koymak konusunda sorun yaşıyorsanız, bunu kolayca yapabilirsiniz ve özel mantık yazmadan yapabilirsiniz.

Rahat ortamlarda kolaylık: nasıl ve neden

Eğer senin oturumları (muhtemelen olduğundan) kurabiye uygulanır ve eğer müşteriler zararlı değildir, ayarlayabileceğiniz bir üst belirli parametreleri değişiklikler yaparak oturumu süresine bağlı. PHP'nin çerezlerle varsayılan oturum işlemeyi kullanıyorsanız, session.gc_maxlifetimebirlikte ayar yapmanın session_set_cookie_paramssizin için çalışması gerekir:

// 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!

Bu, sunucuyu oturum verilerini en az bir saat boyunca işlem yapılmayacak şekilde yapılandırarak ve müşterilerinize aynı zaman aralığından sonra oturum kimliklerini "unutmaları" gerektiğini bildirerek çalışır. Beklenen sonucu elde etmek için bu adımların her ikisi de gereklidir.

  • Müşterilere oturum kimliğini bir saat sonra unutmasını söylemezseniz (veya istemciler kötü amaçlıysa ve talimatlarınızı görmezden gelmeyi seçerse) aynı oturum kimliğini kullanmaya devam eder ve etkin süresi belirleyici olmaz. Bunun nedeni, sunucu tarafında kullanım süresi sona eren oturumların hemen çöp toplama işlemi değil, yalnızca oturumun GC oturum açışında toplanmasıdır .

    GC potansiyel olarak pahalı bir süreçtir, bu nedenle olasılık oldukça küçük veya hatta sıfırdır (çok sayıda isabet alan bir web sitesi olasılıkla GC'yi tamamen terk edecek ve her X dakikada bir arka planda olmasını planlayacaktır). Her iki durumda da (işbirliği yapmayan müşteriler varsayarak) etkili oturum yaşam süreleri için alt sınır olacaktır session.gc_maxlifetime, ancak üst sınır öngörülemez olacaktır.

  • session.gc_maxlifetimeAynı zaman aralığına ayarlamazsanız , sunucu boş oturum verilerini bundan daha önce atabilir; bu durumda, oturum kimliğini hala hatırlayan bir istemci bunu sunar ancak sunucu o oturumla ilişkili hiçbir veri bulamaz ve oturum başlamış gibi davranır.

Kritik ortamlarda kesinlik

Oturum hareketsizliğine bir üst sınır yerleştirmek için özel mantık kullanarak işleri tamamen kontrol edilebilir hale getirebilirsiniz ; yukarıdan gelen alt sınır ile birlikte bu katı bir ayar ile sonuçlanır.

Bunu, üst sınırı oturum verilerinin geri kalanıyla birlikte kaydederek yapın:

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;

Oturum kimliği kalıcılığı

Şimdiye kadar, her oturum kimliğinin kesin değerleriyle hiç ilgilenmedik, sadece verilerin ihtiyaç duyduğumuz sürece var olması şartıyla. Oturum kimliklerinin sizin için önemli olduğu (olası olmayan) durumda, gerektiğinde bunları yeniden oluşturmaya dikkat edilmelidir session_regenerate_id.


Soru: Bunu ararsanız, her dakika söyleyelim, sınırını artıracak mı? örnek 10:00 da denedim, bu yüzden sınırı 11:00, 1 dakika sonra, 10:01, limit 11:01 olacak mı?
oneofakind

@oneofakind: Tam olarak ne ararsanız?
Jon

1
Bunlar: ini_set ('session.gc_maxlifetime', 3600); session_set_cookie_params (3600);
oneofakind

@oneofakind: Evet, ancak yalnızca siz de ararsanız session_start()(aksi takdirde hiçbir etki olmaz) ve yalnızca bu ikisini daha önce her zaman ararsanız session_start(aksi halde gc_maxlifetimeşu anda açık olan tüm oturumları etkileme potansiyeline sahipken session_set_cookie_params, yalnızca yeni başlayan bir oturumu etkileyebilir. mevcut istek).
Jon

@ Session_start () öğesini tekrar ararsam $ _SESSION sürümümdeki her şeyi sıfırlar mı? "tüm oturumu etkileme potansiyeli var" derken nasıl yani? Cevap için teşekkürler.
oneofakind

33

PHP'nin varsayılan oturum işlemeyi kullanıyorsanız, tüm platformlarda oturum süresini güvenilir bir şekilde değiştirmenin tek yolu php.ini dosyasını değiştirmektir . Bunun nedeni, bazı platformlarda, çöp toplama işleminin doğrudan php.ini'den okuyan belirli bir zamanda çalışan bir komut dosyası (bir cron komut dosyası) aracılığıyla uygulanması ve bu nedenle çalışma zamanında, örneğin, aracılığıyla , herhangi bir zamanda değiştirme girişimlerinin güvenilir olmaması ve büyük olasılıkla çalışmaz.ini_set()

Örneğin, Debian Linux sistemlerinde, PHP'nin dahili çöp toplama session.gc_probability=0yapılandırmasında varsayılan olarak ayarlanarak devre dışı bırakılır ve bunun yerine, XX: 09 ve XX: 39'da çalışan /etc/cron.d/php (yani, her yarım saatte bir). Bu cron işi , yapılandırmada belirtilen session.gc_maxlifetime oturumundan daha eski oturumları arar ve varsa bulunursa silinir. Sonuç olarak, bu sistemlerde ini_set('session.gc_maxlifetime', ...)göz ardı edilir. Bu da bu sorunun nedenini açıklıyor: PHP oturumları çok hızlı bir şekilde zaman aşımına uğradı , OP'nin bir ana bilgisayarda sorunları vardı, ancak farklı bir ana bilgisayara geçerken sorunlar sona erdi.

Bu nedenle, php.ini dosyasına erişiminiz olmadığı göz önüne alındığında, taşınabilir olarak yapmak istiyorsanız, varsayılan oturum işlemeyi kullanmak bir seçenek değildir. Görünüşe göre, çerez ömrünü uzatmak ana makineniz için yeterliydi, ancak ana bilgisayarları değiştirseniz bile güvenilir bir şekilde çalışan bir çözüm istiyorsanız, farklı bir alternatif kullanmalısınız.

Mevcut alternatif yöntemler şunları içerir:

  1. Oturumlarınızı PHP'de belirtildiği gibi farklı bir dizine veya veritabanına kaydetmek için PHP'de farklı bir oturum (kaydetme) işleyicisi ayarlayın : böylece cron işi ona ulaşmaz ve yalnızca PHP'ler dahili çöp toplama gerçekleşir. Bu seçenek muhtemelen session.gc_maxlifetimeini_set() değerini ayarlamak için kullanılabilir ancak geri aramdaki maxlifetime parametresini yok saymayı ve kendi kendime maksimum kullanım ömrünü belirlemeyi tercih ederim .gc()

  2. PHP dahili oturum işlemeyi tamamen unutun ve kendi oturum yönetiminizi uygulayın. Bu yöntemin iki ana dezavantajı vardır: kendi küresel oturum değişkenlerinize ihtiyacınız olacak, bu yüzden $_SESSIONsüper küreselin avantajını kaybedersiniz ve daha fazla koda ihtiyaç duyar, bu nedenle hatalar ve güvenlik kusurları için daha fazla fırsat vardır. En önemlisi, oturum kimliği öngörülebilirliğini (olası oturum ele geçirmesine yol açar) önlemek için oturum tanımlayıcı kriptografik olarak güvenli rasgele veya sözde sayılardan üretilmelidir ve PHP ile taşınabilir olarak bu kadar kolay değildir. Ana avantajı, tüm platformlarda tutarlı bir şekilde çalışması ve kod üzerinde tam kontrole sahip olmanızdır. Bu, örneğin phpBB forum yazılımı tarafından alınan yaklaşımdır (en azından sürüm 1; daha yeni sürümlerden emin değilim).

İçin dokümantasyondasession_set_save_handler() (1) örneği vardır . Örnek uzun, ancak burada oturum süresini uzatmak için gerekli değişikliklerle yeniden oluşturacağım. session_set_cookie_params()Çerez ömrünü artırmak için dahil edildiğine dikkat edin.

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

Yaklaşım (2) daha karmaşıktır; temel olarak, tüm oturum işlevlerini kendi başınıza yeniden uygulamanız gerekir. Burada ayrıntılara girmeyeceğim.


Birisi bunu onaylayabilir mi?
Oli

@Oli: Bir el yazısı okumasından sonra doğru görünüyor. Ayrıca stackoverflow.com/questions/520237/… adresine bakmak da isteyebilirsiniz , ancak php.inipratik seçeneklerinize erişiminiz yoksa ciddi şekilde kısıtlanmıştır.
Jon

Ayrıca, Ubuntu 14'te /usr/lib/php5/maxlifetime24 dakikanın altında bir değer hesaplamayacak gibi görünüyor . Böylece oturum zaman aşımlarınızı bundan daha düşük bir değere ayarlayamazsınız.
Henry

"Tamamen PHP dahili oturum işleme unutmak ve kendi oturum yönetimi uygulamak." Tanrım, tehlikeli bir tavsiye. Bir güvenlik kabusu kaçınılmaz olarak ortaya çıkacaktır.
Kzqai

@Kzqai Ayrıca "daha fazla koda ihtiyaç duyar, bu nedenle hatalar ve güvenlik kusurları için daha fazla fırsat vardır". Tavsiye değil, alternatifleri sıralıyorum, ancak iyileştirmek için bir öneriniz varsa, lütfen yapın.
Pedro Gimeno

3

Plesk beni deli ediyor gibi yukarıdakilerden herhangi biriyle ilgili sorunları olan herkes için yorum ekleyerek, PHP betiğinizden session.gc_maxlifetime ayarlayarak Plesk kendi çöp toplama betiğini cron'dan çalıştırdığı için çalışmaz.

Bu sorundan kaçınmak için cron işini saatlik olarak günlük olarak taşıma aşağıdaki bağlantıda yayınlanan çözümü kullandım, o zaman yukarıdaki en iyi cevap işe yarayacak:

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

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


3

$_SESSION['login_time'] = time();Önceki kimlik doğrulama sayfasına koy . Ve oturum zaman aşımını kontrol etmek istediğiniz her diğer sayfada aşağıdan alıntı yapın.

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.
}

Düzenle: Bu, yalnızca diğer yayınlarda ince ayarları kullandıysanız veya Çöp Toplama'yı devre dışı bıraktıysanız ve oturum süresini manuel olarak kontrol etmek istiyorsanız çalışır. Yeniden die()yönlendirmeden sonra eklemeyi unutmayın , çünkü bazı komut dosyaları / robotlar bunu yoksayabilir. Ayrıca, session_destroy()kötü niyetli bir istemci veya robot durumunda, bunun için bir yönlendirmeye güvenmek yerine oturumu doğrudan yok etmek daha iyi bir seçenek olabilir.


2

Paylaşım barındırma sunucusu için veya alan adlarına eklenen bir bildirim =

Ayarlarınızın çalışması için, php_value session.save_path "folderA / sessionsA" kullanarak eklenen etki alanı için farklı bir kaydetme oturumu dizinine sahip olmanız gerekir.

Bu nedenle, kök sunucunuzda public_html içine değil, dışarıdan tanıtım yapılmasına izin verilmeyen bir klasör oluşturun. Cpanel / sunucum için 0700 klasör izinleri iyi çalıştı. Bir deneyin ...

  • php kodu =

     #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');

session_start () öncesinde;

veya

  • .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

Birçok araştırma ve testten sonra bu paylaşılan cpanel / php7 sunucusu için iyi çalıştı. Çok teşekkürler: NoiS


1

Hayır. Php.ini dosyasına erişiminiz yoksa değişikliklerin herhangi bir etkisi olacağını garanti edemezsiniz.

Yine de seanslarınızı uzatmanız gerektiğinden şüpheliyim.
Şu anda oldukça mantıklı bir zaman aşımı var ve bunu genişletmek için bir neden yok.


Merhaba Col, sizinle iletişime geçmenin bir yolunu bulmak için her yere bakıyordum. Son yazımda kapalı olan (Pazar.) Bana bazı önerilerde bulunduğunuzu gördüm. Başka bir projeyle meşgul oldum ve şimdi gitti. Gerçekten önerilerinizi denemek istiyorum. Bu yazdıklarınızı bulmak için yine de var mı?
Yaşlı köpek

Görebildiğim kadarıyla sadece kapalı değil, aynı zamanda silindi. Bu insanların şerefi yok. Evet, sorununuzun bahsettiğim ortak bir çözümü var. Sana e-posta ile yazacağım. Kısacası, bu önceki / sonraki değerleri almak için 2 ek sorgu çalıştırmak üzereydi. SELECT id FROM gallery WHERE SortOrder > $currentsortorder LIMIT 1
Ortak Duygunuz

0

Php.ini dosyasındaki değerleri PHP kodunuzdan geçersiz kılabilirsiniz ini_set().


4
-1: session.gc_maxlifetimeoturumun ömrünü kontrol eden ayar değildir. Bu ayarlarsanız böyle işin dövülerek edilebilir session.gc_divisorüzere 1, ama bu sadece korkunç.
Jon

1
@ SO'da bunun tersini gösteren çok fazla cevap gördüm, neden bu? stackoverflow.com/questions/514155/… stackoverflow.com/questions/9904105/…
giannis christofakis

2
@yannishristofakis: gc_maxlifetimeoturum verilerinin çöp toplama için uygun olacağı aralığı ayarlar - eğer bu kadar zaman geçtikten sonra GC oluşursa, oturum verileri yok edilir (varsayılan ayarlarla bu, oturumun sona ermesiyle aynıdır). Ancak GC, her oturum başlangıcında olasılıkla tetiklenir, bu nedenle oturumun gerçekten sona ereceğine dair bir garanti yoktur - prob vs zaman eğrisini çizebilirsiniz, ancak bir tuğla duvar gibi görünmez. Bu buzdağının sadece görünen kısmı; bkz. stackoverflow.com/questions/520237/…
Jon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.