大學(xué)生實訓(xùn)網(wǎng)站建設(shè)心得關(guān)鍵詞查詢
為什么要序列化
百度百科上關(guān)于序列化的定義是,將對象的狀態(tài)信息轉(zhuǎn)換為可以存儲或傳輸?shù)男问?字符串)的過程。在序列化期間,對象將其當(dāng)前狀態(tài)寫入到臨時或持久性存儲區(qū)(非關(guān)系型鍵值對形式的數(shù)據(jù)庫Redis,與數(shù)組類似)。以后,可以通過從存儲區(qū)中讀取或反序列化對象的狀態(tài),重新創(chuàng)建該對象。
在PHP中,每個類的定義都以關(guān)鍵字class開頭,后面不僅跟著類名還跟著一對花括號,里面包含有類的屬性與方法的定義。
一個類可以包含有屬于自己的屬性(常量:值變量的值不會改變、變量)和方法(函數(shù))。
由于類的實例化對象比較抽象,不方便用于傳輸和存儲。


tips:類為class,對象是object;舉例來說就是,動物為一個大類,大類之后再分小一類如貓貓或者狗狗;而具體的某個動物就為一個對象。一個對象就相當(dāng)于一個變量,對象是一種語言結(jié)構(gòu)。
簡單來說,序列化就是把一個對象變成可以傳輸?shù)淖址?字符串便于傳輸,只需要把字符串賦給變量即可)。在傳遞和保存對象時,為保證對象的完整性和可傳遞性,程序?qū)ο筠D(zhuǎn)換為有序字符串,以保存在本地文件中,可以以特定的格式在進(jìn)程之間跨平臺、安全的進(jìn)行通信。(比如從java平臺傳遞到php平臺)反序列化則根據(jù)字符串中保存的對象狀態(tài)及描述信息,通過反序列化重建對象。
序列化的優(yōu)點:
將對象轉(zhuǎn)為字節(jié)流存儲到硬盤上(實際上是存放在數(shù)據(jù)庫,一般是redis數(shù)據(jù)庫-鍵值對數(shù)據(jù)庫),當(dāng)JVM停機(jī)的話,字節(jié)流還會在硬盤上默默等待,等待下一次JVM的啟動,把序列化的對象,通過反序列化為原來的對象。
序列化后的二進(jìn)制序列能夠減少存儲空間(永久性保存對象)。
序列化成字符串形式的對象可以進(jìn)行網(wǎng)絡(luò)傳輸。
通過序列化可以在進(jìn)程間傳遞對象
實際上用Redis數(shù)據(jù)庫作為緩存,一般用于存儲序列化后的字符串,待字符串需要使用時,再反序列化為對象,方便調(diào)用。
PHP中的序列化與反序列化
反序列化漏洞并不是PHP特有,也存在于Java、Python等語言之中,但其原理基本相通。
PHP反序列化漏洞也叫php對象注入,是一個非常常見的漏洞,這種類型的漏洞雖然有些難以利用,但一旦利用成功就會造成非常危險的后果。
漏洞的形成的根本原因是程序沒有對用戶輸入的反序列化字符串進(jìn)行檢測,導(dǎo)致反序列化過程可以被惡意控制,進(jìn)而造成代碼執(zhí)行、getshell等一系列不可控的后果。
序列化與反序列化的定義
序列化:程序?qū)?span id="vxwlu0yf4" class="kdocs-bold" style="font-weight:bold;">對象狀態(tài)轉(zhuǎn)換為可存儲或傳輸?shù)淖止?jié)序列的過程(即對象狀態(tài)轉(zhuǎn)換為可存儲或者可傳輸?shù)倪^程){序列化是對象轉(zhuǎn)換為字符串的過程}
反序列化:程序把存儲或傳輸?shù)淖止?jié)序列恢復(fù)為對象的過程。{反序列化則是字符串轉(zhuǎn)化為對象的過程}
如果字符串客戶端可控,就會造成web應(yīng)用反序列化任意對象,在反序列化的過程中會觸發(fā)一些可以執(zhí)行的php代碼,例如phpinfo
PHP中的序列化與反序列化,基本都是圍繞serialize()和unserialize()兩個函數(shù)展開的。在介紹這兩個函數(shù)之前,我們可以先看一個簡單的例子。
序列化Demo
序列化會將一個抽象的對象轉(zhuǎn)換為字符串。
我們可以寫一個Demo來說明序列化的過程,首先創(chuàng)建一個類,代碼內(nèi)容如下:
<?php
class student{public $name;public $sex;public $age;public $score;
}
?>

類名是student,該類中有四個變量。接下來,我們可以將這個類實例化,也就是創(chuàng)建一個對象(new),并給對象中變量賦值。代碼如下:
<?php
// 定義一個student類,類中有四個屬性
class student{public $name;public $sex;public $age;public $score;
}// 創(chuàng)建對象1
$student1 = new student();
$student1->name = "wyy";
$student1->sex = false;
$student1->age = 20;
$student1->score = 95;
?>
最后我們使用serialize(),將$student1這個對象序列化成一個字符串。這樣的字符串就很容易傳輸和存儲了。如下:
<?php
// 定義一個student類,類中有四個屬性
class student{public $name;public $sex;public $age;public $score;
}// 創(chuàng)建對象1
$student1 = new student();
$student1->name = "wyy";
$student1->sex = false;
$student1->age = 20;
$student1->score = 95;// 創(chuàng)建對象2
$student2 = new student();
$student2->name = "xcc";
$student2->sex = true;
$student2->age = 25;
$student2->score = 98;// 輸出wyy和xcc的成績
echo $student1->name."'s score = ".$student1->score;
// 進(jìn)行換行
echo "<br/>";
echo $student2->name."'s score = ".$student2->score;// 用var_dump輸出對象
echo "<hr/>";
var_dump($student1);
var_dump($student2);// 對對象進(jìn)行序列化并輸出
echo "<hr>";
echo "序列化后采用echo輸出<br>";
echo serialize($student1);?>
打開瀏覽器訪問該文件,顯示如下,可以看到對象被序列化成字符串:
