การวิเคราะห์ PHP เทคโนโลยีหน้าเว็บแบบไดนามิกเกี่ยวกับคุกกี้และเซสชัน
ผู้เขียน:Eve Cole
เวลาอัปเดต:2009-06-06 18:16:01
1. คุกกี้ PHP
คุกกี้เป็นกลไกที่จัดเก็บข้อมูลบนเบราว์เซอร์ระยะไกลเพื่อติดตามและระบุผู้ใช้
PHP ส่งคุกกี้ในข้อมูลส่วนหัวของโปรโตคอล http ดังนั้นจึงต้องเรียกใช้ฟังก์ชัน setcookie() ก่อนที่จะส่งออกข้อมูลอื่นไปยังเบราว์เซอร์ ซึ่งคล้ายกับข้อจำกัดของฟังก์ชัน header()
1.1 ตั้งค่าคุกกี้:
คุกกี้สามารถตั้งค่าได้โดยใช้ฟังก์ชัน setcookie() หรือ setrawcookie() นอกจากนี้ยังสามารถตั้งค่าได้โดยการส่งส่วนหัว http ไปยังไคลเอนต์โดยตรง
1.1.1 ใช้ฟังก์ชัน setcookie() เพื่อตั้งค่าคุกกี้:
bool setcookie ( ชื่อสตริง [, ค่าสตริง [, int หมดอายุ [, เส้นทางสตริง [, โดเมนสตริง [, บูลปลอดภัย [, บูล httponly]]]]]] )
ชื่อ: ชื่อตัวแปรคุกกี้
ค่า: ค่าของตัวแปรคุกกี้
หมดอายุ: เวลาที่ระยะเวลามีผลบังคับใช้สิ้นสุดลง
เส้นทาง: ไดเรกทอรีที่ถูกต้อง
โดเมน: ชื่อโดเมนที่ถูกต้อง โดเมนระดับบนสุดที่ไม่ซ้ำใคร
ปลอดภัย: หากค่าเป็น 1 คุกกี้จะใช้ได้กับการเชื่อมต่อ https เท่านั้น หากค่าเริ่มต้นคือ 0 ทั้ง http และ https จะถูกต้อง
ตัวอย่าง:
<?php
$value = 'บางสิ่งบางอย่างจากที่ไหนสักแห่ง';
setcookie("TestCookie", $value); /* การตั้งค่าคุกกี้แบบง่าย*/
setcookie("TestCookie", $value, time()+3600); /* ระยะเวลาที่ใช้ได้คือ 1 ชั่วโมง*/
setcookie("TestCookie", $value, time()+3600, "/~rasmus/", ".example.com", 1); /* ไดเรกทอรีที่ถูกต้อง/~rasmus ชื่อโดเมนที่ถูกต้อง example.com และโดเมนย่อยทั้งหมด */
-
ตั้งค่าตัวแปรคุกกี้หลายตัว: setcookie('var[a]','value'); ใช้อาร์เรย์เพื่อแสดงตัวแปร แต่ตัวห้อยไม่จำเป็นต้องใช้เครื่องหมายคำพูด ด้วยวิธีนี้ คุณสามารถใช้ $_COOKIE['var'][ 'a'] เพื่ออ่านตัวแปร COOKIE
1.1.2. ใช้ header() เพื่อตั้งค่าคุกกี้
header("Set-Cookie: name=$value[;path=$path[;domain=xxx.com[;...]]");
พารามิเตอร์ต่อไปนี้เหมือนกับพารามิเตอร์ที่ระบุไว้ข้างต้นสำหรับฟังก์ชัน setcookie
ตัวอย่างเช่น:
$value = 'บางสิ่งบางอย่างจากที่ไหนสักแห่ง';
header("Set-Cookie:name=$value");
1.2 การอ่านคุกกี้:
คุณสามารถใช้ตัวแปร super global ในตัวของ PHP $_COOKIE เพื่ออ่านคุกกี้ทางฝั่งเบราว์เซอร์ได้โดยตรง
ในตัวอย่างข้างต้น คุกกี้ "TestCookie" ได้รับการตั้งค่าแล้ว เรามาอ่านกันดีกว่า:
พิมพ์ $_COOKIE['TestCookie'];
คุกกี้ถูกส่งออกไปแล้วใช่ไหม!
1.3 ลบคุกกี้
เพียงตั้งเวลาที่ถูกต้องให้น้อยกว่าเวลาปัจจุบัน และตั้งค่าให้ว่างเปล่า ตัวอย่างเช่น
setcookie("ชื่อ",",เวลา()-1);
คล้ายกับการใช้ header()
1.4 การแก้ไขปัญหาทั่วไป:
1) มีข้อความแสดงข้อผิดพลาดเมื่อใช้ setcookie() อาจเป็นเพราะมีเอาต์พุตหรือช่องว่างก่อนที่จะเรียก setcookie() อาจเป็นได้ว่าเอกสารของคุณถูกแปลงจากชุดอักขระอื่น และเอกสารอาจมีลายเซ็น BOM ในตอนท้าย (นั่นคือ การเพิ่มอักขระ BOM ที่ซ่อนอยู่ลงในเนื้อหาไฟล์) วิธีแก้ไขคือการป้องกันไม่ให้สถานการณ์นี้เกิดขึ้นในเอกสารของคุณ คุณสามารถจัดการได้เล็กน้อยโดยใช้ฟังก์ชัน ob_start()
2) $_COOKIE ได้รับผลกระทบจาก magic_quotes_gpc และอาจถูกหลีกโดยอัตโนมัติ
3) เมื่อใช้งานจำเป็นต้องทดสอบว่าผู้ใช้รองรับคุกกี้หรือไม่
<!--[ถ้า !supportLineBreakNewLine]-->
1.5 กลไกการทำงานของคุกกี้:
ผู้เรียนบางคนหุนหันพลันแล่นและไม่มีเวลาศึกษาหลักการ เลยเอามาเล่าทีหลัง
ก) เซิร์ฟเวอร์ตั้งค่าคุกกี้ในไคลเอนต์โดยส่งส่วนหัว http Set-Cookie พร้อมการตอบกลับ (คุกกี้หลายตัวต้องการหลายส่วนหัว)
b) ไคลเอนต์ส่งส่วนหัวคุกกี้ http ไปยังเซิร์ฟเวอร์โดยอัตโนมัติ และเซิร์ฟเวอร์จะรับและอ่านมัน
HTTP/1.x 200 ตกลง
X-ขับเคลื่อนโดย: PHP/5.2.1
Set-Cookie: TestCookie=บางสิ่งจากที่ไหนสักแห่ง;
หมดอายุ: พฤหัสบดี 19 พ.ย. 2550 18:52:00 GMT
การควบคุมแคช: ไม่มีร้านค้า, ไม่มีแคช, ต้องตรวจสอบใหม่, หลังตรวจสอบ = 0, ตรวจสอบล่วงหน้า = 0
Pragma: ไม่มีแคช
ประเภทเนื้อหา: text/html
บรรทัดนี้ใช้ฟังก์ชันคุกกี้หลังจากได้รับบรรทัดนี้
Set-Cookie: TestCookie=บางสิ่งจากที่ไหนสักแห่ง;
เบราว์เซอร์จะสร้างไฟล์คุกกี้บนดิสก์ของลูกค้าและเขียน:
TestCookie=บางสิ่งจากที่ไหนสักแห่ง;
-
บรรทัดนี้เป็นผลมาจากการใช้ setcookie('TestCookie','something from some','/'); นอกจากนี้ยังเป็นผลมาจากการใช้ header('Set-Cookie: TestCookie=something fromwhere; path=/') ;.
<!--[สิ้นสุด]-->
2. เซสชัน PHP
เซสชันใช้คุกกี้โดยตั้งค่าเวลาหมดอายุเป็น 0 และใช้ตัวระบุเฉพาะที่เรียกว่า ID เซสชัน (สตริงแบบยาว) เพื่อซิงโครไนซ์ไฟล์เซสชันบางไฟล์บนฝั่งเซิร์ฟเวอร์ (คุณสามารถกำหนดประเภทที่เก็บข้อมูลเซสชันได้ด้วยตัวเอง) และสื่อสารกับ ผู้ใช้ที่เชื่อมต่อ เว็บแอปพลิเคชันจัดเก็บข้อมูลที่เกี่ยวข้องกับเซสชันเหล่านี้และอนุญาตให้ส่งข้อมูลระหว่างเพจกับผู้ใช้
ผู้เยี่ยมชมเว็บไซต์จะได้รับตัวระบุที่ไม่ซ้ำกัน ซึ่งเรียกว่ารหัสเซสชัน มันถูกจัดเก็บไว้ในคุกกี้ฝั่งไคลเอ็นต์หรือส่งผ่าน URL
การสนับสนุนเซสชันอนุญาตให้ผู้ใช้สามารถลงทะเบียนตัวแปรจำนวนเท่าใดก็ได้และสงวนไว้สำหรับแต่ละคำขอ เมื่อผู้เยี่ยมชมเข้าถึงเว็บไซต์ PHP จะตรวจสอบว่ารหัสเซสชันเฉพาะถูกส่งไปในคำขอหรือไม่ ไม่ว่าจะโดยอัตโนมัติ (หากตั้งค่า session.auto_start เป็น 1) หรือเมื่อผู้ใช้ร้องขอ (เรียกอย่างชัดเจนโดย session_start() หรือโดยนัยโดย session_register( )). หากเป็นเช่นนั้น สภาพแวดล้อมที่บันทึกไว้ก่อนหน้านี้จะถูกสร้างขึ้นใหม่
2.1 การส่ง sessionID
2.1.1 ส่ง ID เซสชันผ่านคุกกี้
ใช้ session_start() เพื่อเรียกเซสชัน ขณะสร้างไฟล์เซสชัน เซิร์ฟเวอร์จะสร้างค่าแฮช ID เซสชันและชื่อเซสชันด้วยค่าเริ่มต้นของ PHPSESSID และส่งตัวแปรไปยังไคลเอนต์ (ค่าเริ่มต้นคือ) PHPSESSID (ชื่อเซสชัน ) โดยมีค่าเป็นค่าแฮช 128 บิต เซิร์ฟเวอร์จะโต้ตอบกับไคลเอ็นต์ผ่านคุกกี้นี้
ค่าของตัวแปรเซสชันจะถูกทำให้เป็นอนุกรมภายในโดย PHP และจัดเก็บไว้ในไฟล์ข้อความบนเครื่องเซิร์ฟเวอร์ และโต้ตอบกับคูลีของลูกค้าซึ่งมีชื่อตัวแปรเป็น PHPSESSID ตามค่าเริ่มต้น
นั่นคือ เซิร์ฟเวอร์จะส่งส่วนหัว http โดยอัตโนมัติ: header('Set-Cookie: session_name()=session_id(); path=/');
นั่นคือ setcookie(session_name(),session_id());
เมื่อกระโดดไปยังหน้าใหม่จากหน้านี้และเรียก session_start() PHP จะตรวจสอบข้อมูลเซสชันที่เก็บไว้ฝั่งเซิร์ฟเวอร์ซึ่งเชื่อมโยงกับ ID ที่กำหนด หากไม่พบ ชุดข้อมูลใหม่จะถูกสร้างขึ้น
2.1.2 ส่ง ID เซสชันผ่าน URL
วิธีการนี้จะใช้เฉพาะเมื่อผู้ใช้ห้ามการใช้คุกกี้ เนื่องจากคุกกี้ของเบราว์เซอร์เป็นแบบสากลอยู่แล้ว และด้วยเหตุผลด้านความปลอดภัย จึงไม่จำเป็นต้องใช้วิธีนี้
<a href="p.php?<?php print session_name() ?>=<?php print session_id() ?>">xxx</a> ค่าเซสชันยังสามารถส่งผ่าน POST ได้อีกด้วย
2.2 ตัวอย่างการใช้งานเซสชันเบื้องต้น
<?php
// page1.php
session_start();
echo 'ยินดีต้อนรับสู่หน้าที่ 1';
/* สร้างตัวแปร session และกำหนดค่าให้กับตัวแปร session */
$_SESSION['favcolor'] = 'สีเขียว';
$_SESSION['สัตว์'] = 'แมว';
$_SESSION['time'] = เวลา();
// หากไคลเอนต์ใช้คุกกี้ เซสชันสามารถส่งผ่านโดยตรงไปยัง page2.php
echo '<br /><a href="page2.php">หน้า 2</a>';
// หากไคลเอนต์ปิดใช้งานคุกกี้
echo '<br /><a href="page2.php? . SID . '">หน้า 2</a>';
-
ตามค่าเริ่มต้น ภายใต้ php5.2.1 SID จะมีค่าเมื่อมีการเขียนคุกกี้เท่านั้น
มีคุกกี้ที่เกี่ยวข้องอยู่แล้ว จากนั้น SID จะว่างเปล่า (ไม่ได้กำหนด)
-
-
<?php
// page2.php
session_start();
พิมพ์ $_SESSION['animal']; // พิมพ์เซสชันเดียว
var_dump($_SESSION); // พิมพ์ค่าเซสชันที่ส่งผ่านโดย page1.php
-
2.3 ใช้ฟังก์ชันเซสชันเพื่อควบคุมการแคชหน้า
ในหลายกรณี เราจำเป็นต้องตรวจสอบว่าหน้าเว็บของเราถูกแคชไว้บนไคลเอนต์ หรือตั้งเวลาความถูกต้องของแคช ตัวอย่างเช่น มีเนื้อหาที่ละเอียดอ่อนบางอย่างบนหน้าเว็บของเรา และคุณต้องเข้าสู่ระบบเพื่อดูเนื้อหานั้น คุณสามารถเปิดแคชในเครื่องได้โดยตรง คุณสามารถท่องเว็บโดยไม่ต้องเข้าสู่ระบบ
ใช้ session_cache_limiter('private'); เพื่อควบคุมแคชของเพจไคลเอ็นต์ ซึ่งจะต้องถูกเรียกก่อน session_start()
สำหรับพารามิเตอร์เพิ่มเติม โปรดดูการควบคุมแคชไคลเอ็นต์ที่ http://blog.chinaunix.net/u/27731/showart.php?id=258087
หากต้องการควบคุมเวลาแคชไคลเอ็นต์ ให้ใช้ session_cache_expire(int) หน่วย (s) และจะต้องถูกเรียกก่อน session_start()
นี่เป็นเพียงวิธีการควบคุมแคชเมื่อใช้เซสชัน เรายังสามารถควบคุมแคชของเพจในส่วนหัว ()
2.4 ลบเซสชัน
ต้องใช้เวลาสามขั้นตอนเพื่อให้บรรลุ
<?php
session_destroy(); // ขั้นตอนแรก: ลบไฟล์เซสชันฝั่งเซิร์ฟเวอร์ ซึ่งใช้
setcookie(session_name(),'',time()-3600); // ขั้นตอนที่ 2: ลบเซสชันจริง:
$_SESSION = array(); // ขั้นตอนที่ 3: ลบอาร์เรย์ตัวแปรโกลบอล $_SESSION
-
2.5 การใช้เซสชันในแอปพลิเคชันเว็บขนาดใหญ่ของ PHP สำหรับไซต์ที่มีการเข้าชมจำนวนมาก วิธีการจัดเก็บเซสชันเริ่มต้นไม่เหมาะสม function bool session_set_save_handler (callback open, callback close, callback read, callback write, callback destroy, callback gc) เป็นวิธีการแก้ปัญหาที่มอบให้เราในการแก้ปัญหานี้
6 ฟังก์ชั่นที่ใช้โดยฟังก์ชั่นนี้มีดังนี้:
1. bool open() ใช้เพื่อเปิดกลไกการจัดเก็บเซสชัน
2. bool close() ปิดการดำเนินการจัดเก็บข้อมูลเซสชัน
3. mixde read() ใช้ฟังก์ชันนี้เมื่อโหลดข้อมูลเซสชันจากที่จัดเก็บข้อมูล
4. bool write() เขียนข้อมูลทั้งหมดของ ID เซสชันที่กำหนดไปยังที่เก็บข้อมูล
5. bool destroy() ทำลายข้อมูลที่เกี่ยวข้องกับ ID เซสชันที่ระบุ
6. bool gc() สำหรับตัวอย่างการรวบรวมข้อมูลขยะในระบบจัดเก็บข้อมูล โปรดดูฟังก์ชัน session_set_save_handler() ในคู่มือ PHP
หากคุณใช้คลาสเพื่อจัดการให้ใช้
session_set_save_handler(
อาร์เรย์('ชื่อคลาส','เปิด'),
อาร์เรย์('ชื่อคลาส','ปิด'),
array('ชื่อคลาส','อ่าน'),
อาร์เรย์('ชื่อคลาส','เขียน'),
อาร์เรย์('ชื่อคลาส','ทำลาย'),
อาร์เรย์('ชื่อคลาส','gc'),
-
การเรียกเมธอดแบบคงที่ 6 วิธีในคลาส className สามารถเปลี่ยนแปลง ClassName เป็นอ็อบเจ็กต์ได้ ดังนั้นจึงไม่จำเป็นต้องเรียกเมธอดแบบสแตติก อย่างไรก็ตาม การใช้สมาชิกแบบคงที่ไม่จำเป็นต้องสร้างอ็อบเจ็กต์ และประสิทธิภาพจะดีกว่า
2.6 ฟังก์ชั่นเซสชันที่ใช้กันทั่วไป:
บูล session_start (เป็นโมฆะ); เริ่มต้นเซสชัน
bool session_destroy(void): ลบไฟล์ที่เกี่ยวข้องกับเซสชันฝั่งเซิร์ฟเวอร์
string session_id() ID ของเซสชันปัจจุบัน
string session_name() ชื่อเซสชันที่เข้าถึงในปัจจุบัน ซึ่งเป็นชื่อคุกกี้ที่ไคลเอ็นต์บันทึก ID เซสชัน ค่าเริ่มต้นคือ PHPSESSID
array session_get_cookie_params() รายละเอียดเซสชันที่เกี่ยวข้องกับเซสชันนี้
string session_cache_limiter() ควบคุมแคชไคลเอ็นต์ของเพจโดยใช้เซสชัน
ini session_cache_expire() ควบคุมเวลาแคชไคลเอนต์
bool session_destroy() ลบไฟล์ที่บันทึกข้อมูลเซสชันทางฝั่งเซิร์ฟเวอร์
ถือเป็นโมฆะ session_set_cookie_params ( int อายุการใช้งาน [, เส้นทางสตริง [, โดเมนสตริง [, บูลปลอดภัย [, บูล httponly]]]] ) ตั้งค่ารายละเอียดเซสชันที่เกี่ยวข้องกับเซสชันนี้
bool session_set_save_handler (callback open, callback close, callback read, callback write, callback destroy, callback gc) กำหนดฟังก์ชันสำหรับการประมวลผลเซสชัน (ไม่ได้ใช้วิธีเริ่มต้น)
bool session_regenerate_id([bool Delete_old_session]) กำหนดรหัสเซสชันใหม่
2.7 ปัญหาด้านความปลอดภัยของเซสชัน ผู้โจมตีใช้ความพยายามอย่างมากในการพยายามรับรหัสเซสชันที่มีประสิทธิภาพของผู้ใช้ที่มีอยู่ ด้วยรหัสเซสชัน พวกเขาอาจมีความสามารถเช่นเดียวกับผู้ใช้รายนี้ในระบบ
ดังนั้น แนวทางแก้ไขหลักของเราคือการตรวจสอบความถูกต้องของรหัสเซสชัน
<?php
ถ้า(!isset($_SESSION['user_agent'])){
$_SESSION['user_agent'] = $_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT'];
-
/* หากรหัสเซสชันผู้ใช้ถูกปลอมแปลง*/
elseif ($_SESSION['user_agent'] != $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']) {
session_regenerate_id();