魔術引號是 PHP 早期為防禦 SQL 注入而引入的自動轉義機制。當 magic_quotes_gpc = On 時,所有 GET、POST、COOKIE 資料的單引號、雙引號、反斜線、NULL 字元會自動加上反斜線轉義(相當於 addslashes())。
| 指令 | 影響範圍 | 預設值 | 執行期可改 |
|---|---|---|---|
| magic_quotes_gpc | HTTP 請求資料(G/P/C) | On (PHP 5.3 前) | 否 |
| magic_quotes_runtime | 外部資料來源(資料庫、檔案等) | Off | 是 (ini_set) |
| magic_quotes_sybase | 單引號轉義方式(單引號雙寫 vs 反斜線) | Off | 是 |
magic_quotes_* 指令。若維護舊專案需同時支援有/無魔術引號環境,可使用以下函式統一處理:
<?php
function filterInputData($data) {
if (is_array($data)) {
return array_map('filterInputData', $data);
}
// 若魔術引號開啟,先移除自動加的反斜線
if (get_magic_quotes_gpc()) {
$data = stripslashes($data);
}
// 統一使用資料庫專用轉義(以 PDO 為例)
// 實際專案請改用 Prepared Statements,勿手動轉義
return $data;
}
// 在入口檔案最早處呼叫
$_GET = filterInputData($_GET);
$_POST = filterInputData($_POST);
$_COOKIE = filterInputData($_COOKIE);
$_REQUEST = filterInputData($_REQUEST);
?>
徹底解決注入問題,不依賴任何轉義設定:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'user', 'pass');
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email AND status = :status');
$stmt->execute([':email' => $email, ':status' => 1]);
$user = $stmt->fetch();
?>
魔術引號是歷史產物,現代 PHP 開發應完全關閉並遷移至 Prepared Statements。舊專案若無法立即重構,請在入口統一清理 stripslashes() 並儘快規劃重寫資料存取層。