false。<?php
$arr = ['id' => 1, 'name' => '測試', 'tags' => ['php', 'serialize']];
$str = serialize($arr);
echo $str;
// 輸出:a:3:{s:2:"id";i:1;s:4:"name";s:6:"測試";s:4:"tags";a:2:{i:0;s:3:"php";i:1;s:9:"serialize";}}
// 格式說明:
// a:3 => 陣列 3 元素
// s:2:"id" => 長度 2 字串 "id"
// i:1 => 整數 1
// s:6:"測試" => 長度 6 位元組字串(UTF-8 中文佔 3 位元組)
// 物件格式:O:類別名長度:"類別名":屬性數:{...}
?>
__sleep / __wakeup<?php
class User {
public $id;
public $name;
private $password; // 敏感欄位不想序列化
private $db; // 資源型別不可序列化
public function __construct($id, $name, $password) {
$this->id = $id;
$this->name = $name;
$this->password = $password;
$this->db = new PDO('sqlite::memory:');
}
// 序列化前調用:指定要保存的屬性名稱陣列
public function __sleep(): array {
return ['id', 'name']; // 排除 password、db
}
// 反序列化後調用:重新建立資源連線
public function __wakeup(): void {
$this->db = new PDO('sqlite::memory:');
$this->password = '***'; // 重置敏感欄位
}
}
$user = new User(1, 'Alice', 'secret123');
$serialized = serialize($user);
echo $serialized . "\n";
// O:4:"User":2:{s:2:"id";i:1;s:4:"name";s:5:"Alice";} // 只有 id、name
$restored = unserialize($serialized);
var_dump($restored); // password 為 '***', db 為新 PDO 實例
?>
| 場景 | 說明 | 注意事項 |
|---|---|---|
| Session 儲存複雜資料 | 預設 Session 處理器內部即使用 serialize | 資料量大時考慮 igbinary 或資料庫儲存 |
| 快取物件/陣列 | Redis/Memcached 存入序列化字串 | 注意反序列化效能,熱資料用原生格式 |
| 跨程序傳遞資料 | CLI 腳本間透過檔案/管道傳遞結構化資料 | 版本一致性:類別定義必須存在且相容 |
| 資料庫欄位存儲陣列 | 不想建關聯表時,將陣列序列化存 TEXT 欄位 | 無法直接 SQL 查詢內部值,僅適合整體讀寫 |
| API 回應快取 | 將回應物件序列化存檔,下次直接輸出 | 需處理快取失效與結構變更遷移 |
絕對不要 對不可信輸入(如 $_GET, $_COOKIE, $_POST)直接呼叫 unserialize()。
<?php
// 危險範例:攻擊者可構造惡意序列化字串觸發 __wakeup/__destruct 鏈(POP Chain)
$data = $_COOKIE['data'];
$obj = unserialize($data); // 嚴重安全漏洞!
// 安全做法:
// 1. 使用 JSON (json_encode/json_decode) 替代,不支援物件但無代碼執行風險
// 2. 若必須用 serialize,啟用 PHP 7.0+ 的 allowed_classes 選項
$obj = unserialize($data, ['allowed_classes' => ['MySafeClass']]); // 只允許白名單類別
// 3. 簽名驗證:儲存時簽名,讀取時驗證完整性
$payload = serialize($data);
$signed = $payload . '.' . hash_hmac('sha256', $payload, SECRET_KEY);
// 讀取時驗證簽名再 unserialize
?>
session.serialize_handler = igbinary。__sleep 回傳不存在屬性、Serializable 介面(改用 __serialize/__unserialize)。掌握序列化機制與安全邊界,讓資料持久化與傳輸既方便又可靠。