Session Management: การเริ่มต้น Session
หลังจากที่เราได้เรียนรู้วิธีการเก็บรหัสผ่านอย่างปลอดภัยด้วย password_hash() และตรวจสอบรหัสผ่านด้วย password_verify() ในบทที่แล้ว ขั้นตอนต่อไปที่สำคัญคือการจัดการ Session เพื่อให้ผู้ใช้ที่ล็อกอินแล้วสามารถใช้งานเว็บไซต์ได้โดยไม่ต้องล็อกอินใหม่ทุกครั้งที่เปลี่ยนหน้า
Session คือกลไกที่ช่วยให้เราสามารถเก็บข้อมูลของผู้ใช้ไว้บนเซิร์ฟเวอร์ได้ชั่วคราว ข้อมูลนี้จะถูกส่งกลับไปพร้อมกับการร้องขอ (request) ของผู้ใช้แต่ละราย ทำให้เว็บไซต์สามารถจดจำผู้ใช้และข้อมูลที่เกี่ยวข้องได้ตลอดระยะเวลาที่ผู้ใช้ยังคงใช้งานอยู่ (จนกว่า Session จะหมดอายุหรือถูกทำลาย)
การใช้งาน session_start()
ฟังก์ชัน session_start() คือหัวใจของการจัดการ Session ใน PHP หน้าที่ของมันคือการเริ่มต้น Session ใหม่ หรือดึง Session ที่มีอยู่แล้วจาก Cookie ที่เก็บไว้ใน Browser ของผู้ใช้
ข้อควรจำ: session_start() จะต้องถูกเรียกใช้ ก่อน ที่จะมีการส่ง output ใดๆ ไปยัง Browser (เช่น ก่อนแท็ก HTML ใดๆ หรือก่อนการใช้ echo) มิฉะนั้น PHP จะแสดงข้อผิดพลาด
<?php
// เริ่มต้น Session
session_start();
// ตอนนี้เราสามารถเก็บข้อมูลใน Session ได้แล้ว
$_SESSION['username'] = 'john.doe';
echo "<p>Session ได้เริ่มต้นแล้ว!</p>";
?>
คำอธิบาย:
session_start();: สั่งให้ PHP เริ่มต้น Session หากยังไม่มี Session อยู่ หรือดึง Session ที่มีอยู่แล้ว$_SESSION['username'] = 'john.doe';: เก็บค่า 'john.doe' ไว้ใน Session โดยใช้ key 'username' เราสามารถเข้าถึงค่านี้ได้ในหน้าอื่นๆ ของเว็บไซต์echo "<p>Session ได้เริ่มต้นแล้ว!</p>";: แสดงข้อความว่า Session ได้เริ่มต้นแล้ว
กรณีใช้งานจริง:
สมมติว่าผู้ใช้ล็อกอินเข้าสู่ระบบสำเร็จ เราสามารถเก็บ username และ user ID ไว้ใน Session เพื่อให้เว็บไซต์รู้ว่าใครกำลังใช้งานอยู่
<?php
// หลังจากตรวจสอบ username และ password แล้ว...
if ($username == 'john.doe' && $password == 'secret') {
session_start();
$_SESSION['user_id'] = 123; // สมมติว่า user ID คือ 123
$_SESSION['username'] = $username;
echo "<p>ล็อกอินสำเร็จ! ยินดีต้อนรับ {$username}</p>";
} else {
echo "<p>ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง</p>";
}
?>
ข้อผิดพลาดที่พบบ่อย:
- "session_start(): Cannot send session cookie - headers already sent": เกิดจากการเรียก
session_start()หลังจากที่มีการส่ง output ไปยัง Browser แล้ว ตรวจสอบให้แน่ใจว่าsession_start()อยู่ที่ด้านบนสุดของไฟล์ PHP ก่อนแท็ก HTML หรือคำสั่งechoใดๆ - "session_start(): Failed to read session data": อาจเกิดจากปัญหาในการเข้าถึงไฟล์ Session บนเซิร์ฟเวอร์ ตรวจสอบสิทธิ์การเข้าถึง directory ที่ใช้เก็บ Session (โดยปกติคือ /tmp)
การตั้งค่า Session Cookie
เมื่อ session_start() ถูกเรียกใช้ PHP จะสร้าง Cookie ที่ชื่อ PHPSESSID (โดยค่าเริ่มต้น) ซึ่งจะถูกส่งไปยัง Browser ของผู้ใช้ Cookie นี้มี ID ของ Session ซึ่งใช้เพื่อระบุ Session ของผู้ใช้แต่ละราย
เราสามารถปรับแต่งการทำงานของ Session Cookie ได้โดยใช้ฟังก์ชัน session_set_cookie_params() ก่อนที่จะเรียก session_start()
<?php
// กำหนดค่าพารามิเตอร์ของ Session Cookie
session_set_cookie_params([
'lifetime' => 3600, // ระยะเวลา Cookie (วินาที) - 1 ชั่วโมง
'path' => '/', // Path ที่ Cookie สามารถใช้งานได้
'domain' => '.example.com', // Domain ที่ Cookie สามารถใช้งานได้ (ใส่ . นำหน้าเพื่อให้ใช้ได้กับ subdomain)
'secure' => true, // กำหนดให้ Cookie ส่งผ่านเฉพาะ HTTPS เท่านั้น
'httponly' => true, // ป้องกันการเข้าถึง Cookie จาก JavaScript
'samesite' => 'Lax' // ป้องกัน CSRF (Cross-Site Request Forgery)
]);
// เริ่มต้น Session
session_start();
?>
คำอธิบาย:
lifetime: กำหนดระยะเวลาที่ Cookie จะมีผล (เป็นวินาที) หลังจากระยะเวลานี้ Cookie จะหมดอายุและถูกลบโดย Browser หากไม่ได้กำหนด ค่าเริ่มต้นคือ 0 ซึ่งหมายความว่า Cookie จะอยู่จนกว่า Browser จะถูกปิดpath: กำหนด Path บนเว็บไซต์ที่ Cookie สามารถใช้งานได้ '/' หมายถึง Cookie สามารถใช้งานได้ทุก Pathdomain: กำหนด Domain ที่ Cookie สามารถใช้งานได้ '.example.com' หมายถึง Cookie สามารถใช้งานได้ทั้ง example.com และ subdomain ใดๆ ของ example.comsecure: ถ้าตั้งเป็นtrueCookie จะถูกส่งผ่านเฉพาะ HTTPS เท่านั้น เพื่อป้องกันการดักจับข้อมูลhttponly: ถ้าตั้งเป็นtrueCookie จะไม่สามารถเข้าถึงได้จาก JavaScript เพื่อป้องกัน XSS (Cross-Site Scripting)samesite: ช่วยป้องกัน CSRF โดยกำหนดว่า Cookie จะถูกส่งไปกับ request ที่มาจาก Domain เดียวกันเท่านั้น ค่าที่เป็นไปได้คือ 'Lax', 'Strict', และ 'None'
กรณีใช้งานจริง:
ต้องการให้ Session ของผู้ใช้หมดอายุหลังจากไม่ได้ใช้งาน 30 นาที และต้องการป้องกันการเข้าถึง Cookie จาก JavaScript
<?php
session_set_cookie_params([
'lifetime' => 1800, // 30 นาที (1800 วินาที)
'httponly' => true
]);
session_start();
?>
การตั้งค่า Session Lifetime
นอกจากการตั้งค่า Cookie Lifetime แล้ว เรายังสามารถกำหนด Session Lifetime บนเซิร์ฟเวอร์ได้ด้วย วิธีนี้ช่วยให้เราสามารถควบคุมระยะเวลาที่ข้อมูล Session จะถูกเก็บไว้บนเซิร์ฟเวอร์ได้อย่างละเอียดมากขึ้น
เราสามารถทำได้โดยการกำหนดค่า session.gc_maxlifetime ในไฟล์ php.ini หรือโดยใช้ฟังก์ชัน ini_set()
<?php
// กำหนด Session Lifetime เป็น 1 ชั่วโมง (3600 วินาที)
ini_set('session.gc_maxlifetime', 3600);
session_set_cookie_params([
'lifetime' => 3600, // ต้องกำหนด Cookie Lifetime ให้เท่ากับ Session Lifetime ด้วย
'httponly' => true
]);
session_start();
// รีเฟรช Session ID ทุกครั้งที่โหลดหน้า เพื่อป้องกัน Session Fixation
session_regenerate_id(true);
?>
คำอธิบาย:
ini_set('session.gc_maxlifetime', 3600);: กำหนด Session Lifetime เป็น 3600 วินาที (1 ชั่วโมง)session_regenerate_id(true);: สร้าง Session ID ใหม่ และลบ Session ID เดิม การทำเช่นนี้จะช่วยป้องกัน Session Fixation ซึ่งเป็นช่องโหว่ที่ผู้ไม่ประสงค์ดีสามารถขโมย Session ID ของผู้ใช้ได้
ข้อควรระวัง:
การตั้งค่า session.gc_maxlifetime เพียงอย่างเดียวอาจไม่เพียงพอ เนื่องจาก PHP มีกลไก Garbage Collection ที่จะลบ Session ที่ไม่ได้ใช้งานเป็นระยะๆ เราจึงต้องกำหนด Cookie Lifetime ให้เท่ากับ Session Lifetime เพื่อให้แน่ใจว่า Session จะหมดอายุพร้อมกันทั้งบน Browser และบนเซิร์ฟเวอร์
สรุป:
การเริ่มต้น Session เป็นขั้นตอนสำคัญในการจัดการข้อมูลผู้ใช้บนเว็บไซต์ การใช้ session_start(), session_set_cookie_params() และ ini_set('session.gc_maxlifetime') อย่างถูกต้อง จะช่วยให้เราสามารถสร้างระบบ Session ที่ปลอดภัยและมีประสิทธิภาพได้ ในบทต่อไป เราจะเรียนรู้วิธีการเก็บข้อมูลใน Session และนำไปใช้งานจริง