Keep session data in cookie

ปกติใน php เวลาที่มีการเรียกใช้คำสั่ง session_start() จะเป็นการสั่งให้ php เก็บข้อมูลสำหรับ session นั้นๆ ของผู้ใช้ ซึ่งปกติจะเก็บเป็นไฟล์ไว้ที่ไดเรกทอรี /tmp (แก้ไขตำแหน่งที่เก็บได้ใน php.ini) หรือาจเปลี่ยนวิธีการเก็บไปใช้ shared memory หรือ database ก็ได้ (หรือ storage ใดๆ ตามแต่จะคิดก็ได้)

ข้อมูลส่วนที่เก็บไว้ตรงนี้ ก็คือค่าที่อยู่ในตัวแปร $_SESSION ของผู้ใช้แต่ละคนนั่นเอง ที่เวบปกติจะเก็บค่าตรงนี้ไว้ ก็เพื่อใช้ในประโยชน์ต่างๆ เช่น การล็อกอินเข้าระบบสมาชิก ต้องเก็บข้อมูล member_id กับ member_name ไว้ตลอดทั้ง session ที่สมาชิกเข้ามาใช้งาน

วิธีนี้มันก็มีข้อดีตรงที่ง่าย แต่ปัญหาคือมันต้องมีการอ่านและเขียนฮาร์ดดิสก์เสมอเมื่อมีการเรียกฟังก์ชัน session_start() ซึ่งมันไม่ค่อยดีถ้ามีการใช้งานเยอะๆ และทำให้การขยายระบบทำได้ลำบาก

วิธีเก็บข้อมูลของผู้ใช้ที่ล็อกอินเข้ามาโดยไม่ต้องเก็บลง session สามารถเก็บได้อีกวิธีนึงคือใช้ cookie แต่ข้อเสียของ cookie คือว่า ข้อมูลจะถูกเก็บที่ฝั่งผู้ใช้ ทำให้ผู้ไม่หวังดี อาจจะเปลี่ยนแปลงข้อมูลตรงนี้เพื่อหลอก server ก็ได้ ดังนั้นเพื่อแก้ปัญหาอันนี้ เราก็จะเข้ารหัส cookie ซะโดยใช้วิธีแบบนี้

// สมมุติเราจะเก็บ $member_id กับ $nickname
$data = $member_id."-".$nickname;
// เก็บเวลาไว้ด้วย
$time = time();
// เข้ารหัสซะ
$signed = sha1($secret.$time.$data);
// เอาตัวนี้เก็บใน cookie
$cookie = base64_encode("$signed-$time-$data");

เวลาจะแกะข้อมูลออกมาก็

// แกะออกมาจากที่มัน encode ไว้
$parts = explode("-", base64_decode($cookie), 2);
// เอาทั้งส่วนมา 1 กับ 2 มา sha1 ดูว่าเท่ากับส่วนที่ 0 หรือเปล่า
if (sha1($secret.$parts[1].$parts[2]) == $parts[0]) {
// cookie ถูกต้อง
$data = $parts[2];
// session หมดอายุหรือยัง
if (time() - $parts[2] > 60*60*2) {
// session อยู่มานานเกินสองชั่วโมงแล้ว
}
} else {
// cookie โดนแอบแก้
}

อ่านมาจาก slide ของ Cal Handerson

Leave a Reply