ฉันต้องการที่จะขยายการหมดเวลาเซสชั่นใน PHP
ฉันรู้ว่าเป็นไปได้ที่จะทำเช่นนั้นโดยการแก้ไขไฟล์ php.ini แต่ฉันไม่สามารถเข้าถึงได้
ดังนั้นจึงเป็นไปได้ที่จะทำเฉพาะกับรหัส PHP?
ฉันต้องการที่จะขยายการหมดเวลาเซสชั่นใน PHP
ฉันรู้ว่าเป็นไปได้ที่จะทำเช่นนั้นโดยการแก้ไขไฟล์ php.ini แต่ฉันไม่สามารถเข้าถึงได้
ดังนั้นจึงเป็นไปได้ที่จะทำเฉพาะกับรหัส PHP?
คำตอบ:
การหมดเวลาของเซสชันเป็นแนวคิดที่จะต้องนำไปใช้ในรหัสหากคุณต้องการการค้ำประกันที่เข้มงวด นั่นเป็นวิธีเดียวที่คุณจะมั่นใจได้อย่างแน่นอนว่าไม่มีเซสชันใดจะรอดชีวิตหลังจากไม่มีการใช้งาน X นาที
หากการผ่อนคลายข้อกำหนดนี้เล็กน้อยเป็นที่ยอมรับและคุณสบายดีเมื่อวางขอบเขตล่างแทนขีด จำกัด ที่เข้มงวดกับระยะเวลาคุณสามารถทำได้อย่างง่ายดายและไม่ต้องเขียนตรรกะที่กำหนดเอง
หากเซสชันของคุณถูกนำไปใช้กับคุกกี้ (ซึ่งอาจเป็น) และหากลูกค้าไม่เป็นอันตรายคุณสามารถกำหนดขอบเขตบนของช่วงเวลาเซสชันโดยปรับแต่งพารามิเตอร์บางอย่าง หากคุณใช้การจัดการเซสชั่นเริ่มต้นของ PHP กับคุกกี้การตั้งค่าsession.gc_maxlifetime
พร้อมsession_set_cookie_params
จะทำงานให้คุณเช่นนี้:
// 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!
สิ่งนี้ทำงานได้โดยการกำหนดค่าเซิร์ฟเวอร์เพื่อเก็บข้อมูลเซสชันไว้เป็นเวลาอย่างน้อยหนึ่งชั่วโมงที่ไม่มีการใช้งานและสั่งให้ไคลเอ็นต์ของคุณทราบว่าพวกเขาควร "ลืม" รหัสเซสชันของพวกเขาหลังจากช่วงเวลาเดียวกัน ต้องใช้ทั้งสองขั้นตอนเพื่อให้บรรลุผลตามที่คาดหวัง
หากคุณไม่บอกให้ลูกค้าลืมรหัสเซสชันหลังจากผ่านไปหนึ่งชั่วโมง (หรือหากลูกค้าประสงค์ร้ายและเลือกที่จะเพิกเฉยต่อคำแนะนำของคุณ) พวกเขาจะใช้รหัสเซสชันเดิมต่อไปและระยะเวลาที่มีประสิทธิภาพจะไม่กำหนดขึ้น นั่นเป็นเพราะเซสชันที่อายุการใช้งานหมดอายุบนฝั่งเซิร์ฟเวอร์จะไม่ถูกเก็บรวบรวมขยะทันที แต่เฉพาะเมื่อใดก็ตามที่เซสชัน GC เข้ามา
GC เป็นกระบวนการที่มีราคาแพงดังนั้นโดยทั่วไปความน่าจะเป็นนั้นค่อนข้างเล็กหรือเป็นศูนย์ (เว็บไซต์ที่ได้รับความนิยมจำนวนมากอาจทำให้ GC น่าจะเป็นไปได้ทั้งหมดและกำหนดให้มันเกิดขึ้นในพื้นหลังทุก ๆ X นาที) ในทั้งสองกรณี (สมมติว่าลูกค้าที่ไม่ร่วมมือ) ขอบเขตที่ต่ำกว่าสำหรับช่วงเวลาเซสชันที่มีประสิทธิภาพจะเป็นsession.gc_maxlifetime
แต่ขอบเขตบนจะไม่แน่นอน
หากคุณไม่ได้ตั้งค่าsession.gc_maxlifetime
ช่วงเวลาเดียวกันเซิร์ฟเวอร์อาจละทิ้งข้อมูลเซสชันว่างก่อนหน้านั้น ในกรณีนี้ลูกค้าที่ยังคงจดจำรหัสเซสชันของตนจะแสดง แต่เซิร์ฟเวอร์จะไม่พบข้อมูลที่เกี่ยวข้องกับเซสชันนั้นทำงานได้อย่างมีประสิทธิภาพราวกับว่าเซสชันเพิ่งเริ่มทำงาน
คุณสามารถควบคุมทุกสิ่งได้อย่างสมบูรณ์โดยใช้ตรรกะที่กำหนดเองเพื่อวางขอบเขตบนบนการไม่ใช้งานเซสชัน พร้อมกับขอบล่างจากด้านบนผลลัพธ์นี้ในการตั้งค่าที่เข้มงวด
ทำสิ่งนี้โดยการบันทึกขอบเขตบนพร้อมกับส่วนที่เหลือของข้อมูลเซสชัน:
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;
จนถึงตอนนี้เรายังไม่ได้กังวลกับค่าที่แน่นอนของแต่ละ ID เซสชั่นเฉพาะกับข้อกำหนดที่ว่าข้อมูลควรมีอยู่ตราบเท่าที่เราต้องการให้พวกเขา โปรดทราบว่าในกรณีที่ไม่น่าเป็นไปได้ว่าเซสชันนั้นมีความสำคัญกับคุณคุณจะต้องระมัดระวังในการสร้างขึ้นมาใหม่session_regenerate_id
เมื่อจำเป็น
session_start()
ด้วย (ไม่เช่นนั้นจะไม่มีผลใด ๆ ) และเฉพาะในกรณีที่คุณโทรหาทั้งสองก่อนหน้านี้เสมอsession_start
(มิฉะนั้นgc_maxlifetime
อาจมีผลกระทบต่อเซสชันทั้งหมดที่เปิดอยู่ในขณะsession_set_cookie_params
นี้เท่านั้น คำขอปัจจุบัน)
ถ้าคุณใช้การจัดการเซสชั่นเริ่มต้นของ PHP, วิธีเดียวที่จะเชื่อถือได้เปลี่ยนระยะเวลาการใช้งานในทุกแพลตฟอร์มคือการเปลี่ยนแปลงphp.ini นั่นเป็นเพราะในบางแพลตฟอร์มการรวบรวมขยะจะดำเนินการผ่านสคริปต์ที่ทำงานทุกเวลา ( สคริปต์cron ) ที่อ่านโดยตรงจากphp.iniดังนั้นความพยายามใด ๆ ที่จะเปลี่ยนมันในเวลาทำงานเช่นผ่านini_set()
ไม่น่าเชื่อถือและเป็นไปได้มากที่สุด จะไม่ทำงาน
ตัวอย่างเช่นในระบบ Debian Linux การรวบรวมขยะภายในของ PHP ถูกปิดใช้งานโดยการตั้งค่าsession.gc_probability=0
เริ่มต้นในการกำหนดค่าและจะทำแทนผ่าน /etc/cron.d/php ซึ่งทำงานที่ XX: 09 และ XX: 39 (นั่นคือ ทุกครึ่งชั่วโมง) งาน cron นี้ค้นหาเซสชันที่เก่ากว่าsession.gc_maxlifetime ที่ระบุในการกำหนดค่าและหากพบสิ่งใดสิ่งเหล่านั้นจะถูกลบออก เป็นผลให้ในระบบเหล่านี้ini_set('session.gc_maxlifetime', ...)
จะถูกละเว้น นั่นยังอธิบายว่าทำไมในคำถามนี้: เซสชัน PHP หมดเวลาเร็วเกินไป OP มีปัญหาในโฮสต์หนึ่ง แต่ปัญหาหยุดทำงานเมื่อเปลี่ยนไปใช้โฮสต์อื่น
ดังนั้นหากคุณไม่สามารถเข้าถึงphp.iniได้หากคุณต้องการทำแบบพกพาการใช้การจัดการเซสชันเริ่มต้นไม่ใช่ตัวเลือก เห็นได้ชัดว่าการยืดอายุคุกกี้นั้นเพียงพอสำหรับโฮสต์ของคุณ แต่ถ้าคุณต้องการโซลูชันที่ทำงานได้อย่างน่าเชื่อถือแม้ว่าคุณจะเปลี่ยนโฮสต์คุณต้องใช้ทางเลือกอื่น
วิธีการทางเลือกที่มีอยู่รวมถึง:
ตั้งค่าตัวจัดการเซสชั่นที่แตกต่างกัน (บันทึก) ใน PHP เพื่อบันทึกเซสชันของคุณในไดเรกทอรีที่แตกต่างกันหรือในฐานข้อมูลตามที่ระบุไว้ในPHP: Custom Session Handlers (คู่มือ PHP)เพื่อให้งานcronไม่ถึงและ PHP เท่านั้น การรวบรวมขยะภายในจะเกิดขึ้น ตัวเลือกนี้อาจใช้ประโยชน์จากini_set()
การตั้งค่าsession.gc_maxlifetimeแต่ฉันต้องการเพียงแค่ละเว้นพารามิเตอร์maxlifetimeในการgc()
โทรกลับของฉันและกำหนดอายุการใช้งานสูงสุดด้วยตัวเอง
ลืมการจัดการเซสชันภายใน PHP อย่างสมบูรณ์และใช้การจัดการเซสชันของคุณเอง วิธีการนี้มีข้อเสียเปรียบหลักสองประการ: คุณจะต้องใช้ตัวแปรเซสชันทั่วโลกของคุณเองดังนั้นคุณจึงสูญเสียความได้เปรียบจาก$_SESSION
superglobal และต้องการรหัสมากขึ้นจึงมีโอกาสมากขึ้นสำหรับข้อบกพร่องและข้อบกพร่องด้านความปลอดภัย สิ่งสำคัญที่สุดคือตัวระบุเซสชันควรสร้างขึ้นจากตัวเลขสุ่มหรือแบบเทียมที่มีความปลอดภัยแบบเข้ารหัสเพื่อหลีกเลี่ยงการคาดการณ์ ID เซสชัน (นำไปสู่การหักหลังเซสชันที่เป็นไปได้) และนั่นไม่ใช่เรื่องง่ายที่จะทำกับ PHP แบบพกพา ข้อได้เปรียบหลักคือมันจะทำงานได้อย่างต่อเนื่องในทุกแพลตฟอร์มและคุณสามารถควบคุมโค้ดได้อย่างสมบูรณ์ นั่นเป็นวิธีที่นำมาใช้เช่นโดยซอฟต์แวร์ฟอรัมphpBB (อย่างน้อยเวอร์ชัน 1; ฉันไม่แน่ใจเกี่ยวกับเวอร์ชันล่าสุดเพิ่มเติม
มีตัวอย่างของ (1) ในการเป็นเอกสาร session_set_save_handler()
ตัวอย่างมีความยาว แต่ฉันจะทำซ้ำที่นี่ด้วยการแก้ไขที่เกี่ยวข้องที่จำเป็นในการขยายระยะเวลาของเซสชัน บันทึกการรวมของsession_set_cookie_params()
เพื่อเพิ่มอายุการใช้งานคุกกี้ด้วย
<?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
วิธีการ (2) มีความซับซ้อนมากขึ้น โดยทั่วไปคุณจะต้องใช้ฟังก์ชั่นเซสชันทั้งหมดด้วยตัวเองอีกครั้ง ฉันจะไม่ลงรายละเอียดที่นี่
php.ini
ตัวเลือกการปฏิบัติของคุณจะถูก จำกัด อย่างรุนแรง
/usr/lib/php5/maxlifetime
จะไม่คำนวณค่าต่ำกว่า 24 นาที ดังนั้นคุณไม่สามารถตั้งค่าการหมดเวลาเซสชันของคุณให้ต่ำกว่านั้นได้
การเพิ่มความคิดเห็นสำหรับใครก็ตามที่ใช้ Plesk มีปัญหากับข้อใดข้อหนึ่งข้างต้นเพราะมันทำให้ฉันเป็นบ้าการตั้งค่า session.gc_maxlifetime จากสคริปต์ PHP ของคุณจะไม่ทำงานเหมือนที่ Plesk มีสคริปต์การรวบรวมขยะของตัวเองทำงานจาก cron
ฉันใช้วิธีแก้ปัญหาโพสต์ในลิงค์ด้านล่างของการย้ายงาน cron จากรายชั่วโมงเป็นรายวันเพื่อหลีกเลี่ยงปัญหานี้แล้วคำตอบด้านบนควรทำงาน:
mv /etc/cron.hourly/plesk-php-cleanuper /etc/cron.daily/
https://websavers.ca/plesk-php-sessions-timing-earlier-expected
ใส่$_SESSION['login_time'] = time();
ลงในหน้าการตรวจสอบก่อนหน้า และด้านล่างในหน้าอื่น ๆ ที่คุณต้องการตรวจสอบการหมดเวลาของเซสชัน
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.
}
แก้ไข:ใช้งานได้เฉพาะเมื่อคุณใช้การปรับแต่งในโพสต์อื่น ๆ หรือปิดใช้งานการรวบรวมขยะและต้องการตรวจสอบระยะเวลาเซสชันด้วยตนเอง อย่าลืมเพิ่มdie()
หลังจากเปลี่ยนเส้นทางเนื่องจากสคริปต์ / โรบ็อตบางตัวอาจเพิกเฉย นอกจากนี้การทำลายเซสชั่นโดยตรงด้วยsession_destroy()
แทนที่จะพึ่งพาการเปลี่ยนเส้นทางสำหรับที่อาจเป็นตัวเลือกที่ดีกว่าอีกครั้งในกรณีของลูกค้าที่เป็นอันตรายหรือหุ่นยนต์
เพียงแจ้งให้ทราบล่วงหน้าสำหรับการโฮสต์เซิร์ฟเวอร์ที่ใช้ร่วมกันหรือเพิ่มในโดเมน
เพื่อให้การตั้งค่าของคุณใช้งานได้คุณจะต้องมีเซสชันบันทึกที่ต่างออกไปสำหรับโดเมนที่เพิ่มโดยใช้ php_value session.save_path "folderA / timesA"
ดังนั้นสร้างโฟลเดอร์ไปยังเซิร์ฟเวอร์รูทของคุณไม่ใช่ใน public_html และไม่ให้เข้าถึงจากภายนอก สำหรับ cpanel / เซิร์ฟเวอร์ของฉันทำงานได้ดีการอนุญาตของโฟลเดอร์ 0700 ลอง ...
โค้ด 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');
ก่อน session_start ();
หรือ
.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
หลังจากการค้นคว้าและทดสอบหลายอย่างสิ่งนี้ใช้ได้ผลดีกับเซิร์ฟเวอร์ cpanel / php7 ที่ใช้ร่วมกัน ขอบคุณมาก: NoiS
ไม่หากคุณไม่มีสิทธิ์เข้าถึง php.ini คุณไม่สามารถรับประกันได้ว่าการเปลี่ยนแปลงจะมีผลกระทบใด ๆ
ฉันสงสัยว่าคุณต้องยืดเวลาการเรียนของคุณออกไป
ขณะนี้มีการหมดเวลาที่สมเหตุสมผลในขณะนี้และไม่มีเหตุผลที่จะขยายเวลา
SELECT id FROM gallery WHERE SortOrder > $currentsortorder LIMIT 1
คุณสามารถแทนที่ค่าใน php.ini จากโค้ด PHP ini_set()
ของคุณโดยใช้
session.gc_maxlifetime
ไม่ใช่การตั้งค่าที่ควบคุมอายุการใช้งานเซสชัน มันสามารถกระบองในการทำงานเช่นว่าถ้าคุณตั้งsession.gc_divisor
ไป1
แต่ที่น่ากลัวเพียง
gc_maxlifetime
ตั้งค่าช่วงเวลาหลังจากที่ข้อมูลเซสชันมีสิทธิ์สำหรับการรวบรวมขยะ - หาก GC เกิดขึ้นหลังจากเวลาผ่านไปนานมากข้อมูลเซสชันจะถูกทำลาย (ด้วยการตั้งค่าเริ่มต้นซึ่งเหมือนกับการหมดอายุเซสชัน) แต่ GC ถูกเรียกใช้ความน่าจะเป็นในการเริ่มต้นแต่ละเซสชันดังนั้นจึงไม่มีการรับประกันว่าเซสชันนั้นจะหมดอายุจริง ๆ - คุณสามารถเขียนกราฟของเวลาเทียบกับเวลาได้ แต่มันจะไม่ดูเหมือนกำแพงอิฐ นั่นเป็นเพียงส่วนปลายของภูเขาน้ำแข็ง; ดูstackoverflow.com/questions/520237/…